2017-06-05 136 views
0

我需要使用WinAPI和环形缓冲区从主线程向我创建的线程发送消息。通过线程之间的环形(循环)缓冲区发送消息(C中)

我定义了结构并为我的环形缓冲区写了函数。 环形缓冲区 - 它包含头部,尾部,大小和指向具有数据和数据本身长度的结构描述符的指针。因为我需要发送2个参数给CreateThread函数,所以我创建了第三个结构ThreadParams来保存2个参数。

我想离开这个结构他们现在如何,不可改变。

typedef struct _Descriptor 
{ 
    uint32_t dataLen; 
    void * data; 
} Descriptor; 

typedef struct _ringBuffer 
{ 
    Descriptor *bufferData; 
    int head; 
    int tail; 
    int size; 
} ringBuffer; 

typedef struct _ThreadParams 
{ 
    void * ptr1; 
    void * ptr2; 
} ThreadParams; 

有我的环形缓冲区功能的实现:

void bufferFree(ringBuffer *buffer) 
{ 
    free(buffer->bufferData); 
} 

void ringInitialization(ringBuffer *buffer, int size) 
{ 
    buffer->size = size; 
    buffer->head = 0; 
    buffer->tail = 0; 
    buffer->bufferData = (Descriptor*)malloc(sizeof(Descriptor) * size); 
} 

int pushBack(ringBuffer *buffer, void * data) // fill buffer 
{ 
    buffer->bufferData[buffer->tail++] = *(Descriptor*)data; 
    if (buffer->tail == buffer->size) 
    { 
     buffer->tail = 0; 
    } 
    return 0; 
} 

int popFront(ringBuffer *buffer) 
{ 
    if (buffer->head != buffer->tail) 
    { 
     buffer->head++; 
     if (buffer->head == buffer->size) 
     { 
      buffer->head = 0; 
     } 
    } 
    return 0; 
} 

我的主:我检查,我可以派几个字节(内存线程之间共享),现在我需要发送大消息(> BUFF_SIZE)虽然环缓冲我想在while()循环中做什么。这是一个问题:我该怎么做?我的东西不起作用,因为我在printf()函数中捕获了一个异常(内存访问冲突)。

#include <stdio.h> 
#include <stdlib.h> 
#include <conio.h> 
#include <windows.h> 
#include <strsafe.h> 
#include <stdint.h> 

#define RING_SIZE 256 
#define BUFFER_SIZE 1024 

DWORD WINAPI HandleSendThread(LPVOID params); 

uint8_t * getPointer(uint8_t *buffer, uint32_t index) 
{ 
    uint8_t * ptr = ((uint8_t*)buffer) + index * BUFFER_SIZE; 
    return ptr; 
} 

int main(int argc, char * argv[])  
{ 
    //Descriptor * ringData = (Descriptor *)malloc(sizeof(Descriptor) * RING_SIZE); 

    ringBuffer ring; 
    ringInitialization(&ring, RING_SIZE); 
    void * packetBuffer = malloc(BUFFER_SIZE * RING_SIZE); 
    uint8_t * currentBuffer = getPointer(packetBuffer, 0); 
    uint8_t * str = "Mr. and Mrs. Dursley, of number four, Privet Drive, were proud to say that they were perfectly normal, thank you very much. They were the last people you'd expect to be involved in anything strange or mysterious, because they just didn't hold with such nonsense. Mr.Dursley was the director of a firm called Grunnings, which made drills.He was a big, beefy man with hardly any neck, although he did have a very large mustache.Mrs.Dursley was thin and blonde and had nearly twice the usual amount of neck, which came in very useful as she spent so much of her time craning over garden fences, spying on the neighbors.The Dursleys had a small son called Dudley and in their opinion there was no finer boy anywhere."; 

    strcpy(currentBuffer, str); 
    ring.bufferData[0].data = currentBuffer; 
    ring.bufferData[0].dataLen = strlen(str); 

    int currentSize = 0; 
    int ringSize = RING_SIZE; 
    while(ring.bufferData[0].data != '\0') 
    { 
     for (int i = currentSize; i < ringSize; i + RING_SIZE) 
     { 
      pushBack(&ring, currentBuffer); 
      printf("h = %s, tail = %s, dataBuffer = %s\n", (char*)ring.head, (char*)ring.tail, (char*)ring.bufferData[i].data); 
     } 
     currentSize = ringSize; 
     ringSize = 2 * ringSize; 
     popFront(&ring); 
    } 

    ThreadParams params = { &ring, packetBuffer }; 
    HANDLE MessageThread = 0; 
    MessageThread = CreateThread(NULL, 0, HandleSendThread, &params, 0, NULL); 
    if (MessageThread == NULL) 
    { 
     ExitProcess(MessageThread); 
    } 

    WaitForSingleObject(MessageThread, INFINITE); 
    CloseHandle(MessageThread); 
    system("pause"); 
    return 0; 
} 

而且我CreateThread函数:

DWORD WINAPI HandleSendThread(LPVOID params) 
{ 
    ringBuffer * ring = ((ThreadParams*)params)->ptr1; 
    void * buffer = ((ThreadParams*)params)->ptr2; 
    //ring->bufferData[0].dataLen = sizeof(buffer) + sizeof(ring->bufferData[0])*1024; 

    printf("Shared memory check: ringBuffer data = \"%s\", \nlength = %d\n", (char*)ring->bufferData[0].data, ring->bufferData[0].dataLen); 
    return 0; 
} 
+2

'params'是一个局部变量,它不再当线程开始运行存在。 ++运算符是read-modify-write,因此不是线程安全的。 ' –

+1

'ring.bufferData [0] .dataLen = strlen(str);'不,这不对。 – ThingyWotsit

+1

@HansPassant是的,但主线程停留在WaitForSingleObject上,因此本地var生存期是确定的。 – ThingyWotsit

回答

0

实测值的溶液

int main(int argc, char * argv[]) 
{ 
    ringBuffer ring; 
    ringInitialization(&ring, RING_SIZE); 
    void * packetBuffer = malloc(BUFFER_SIZE * RING_SIZE); 
    Descriptor temp = { 0 }; 
    uint8_t * currentBuffer = getPointer(packetBuffer, 0); 
    uint8_t * str = "Mr. and Mrs. Dursley, of number four, Privet Drive, were proud to say that they were perfectly normal, thank you very much. They were the last people you'd expect to be involved in anything strange or mysterious, because they just didn't hold with such nonsense. Mr.Dursley was the director of a firm called Grunnings, which made drills.He was a big, beefy man with hardly any neck, although he did have a very large mustache.Mrs.Dursley was thin and blonde and had nearly twice the usual amount of neck, which came in very useful as she spent so much of her time craning over garden fences, spying on the neighbors.The Dursleys had a small son called Dudley and in their opinion there was no finer boy anywhere."; 

    strcpy(currentBuffer, str); 
    temp.dataLen = strlen(str); 
    temp.data = currentBuffer; 

    pushBack(&ring, &temp); 
    ThreadParams params = { &ring, packetBuffer }; 
    HANDLE MessageThread = 0; 
    MessageThread = CreateThread(NULL, 0, HandleSendThread, &params, 0, NULL); 
    if (MessageThread == NULL) 
    { 
     ExitProcess(MessageThread); 
    } 
    WaitForSingleObject(MessageThread, INFINITE); 
    CloseHandle(MessageThread); 
    system("pause"); 
    return 0; 
} 

DWORD WINAPI HandleSendThread(LPVOID params) 
{ 
    ringBuffer * ring = ((ThreadParams*)params)->ptr1; 
    void * buffer = ((ThreadParams*)params)->ptr2; 
    Descriptor * temp = &ring->bufferData[ring->head]; 

    for (int i = 0; i < temp->dataLen; i++) 
    { 
     printf("%c", ((char*)temp->data)[i]); 
    } 
    printf("\n"); 
    return 0; 
} 
0

你最直接的问题是pushBack()在主函数的代码的代码之间的矛盾,这预计data指向一个Descriptor,并且,这代之以传递一个指向字符串的指针。

如果你已经宣布pushBack()正确,即

void pushBack(ringBuffer *buffer, Descriptor * data) 
{ 
    buffer->bufferData[buffer->tail++] = *data; 
    if (buffer->tail == buffer->size) 
    { 
     buffer->tail = 0; 
    } 
} 

那么编译器就已经能够提醒你有关的差异。

你这儿也有一个无限循环:

for (int i = currentSize; i < ringSize; i + RING_SIZE) 

你可能是指

for (int i = currentSize; i < ringSize; i += RING_SIZE) 

...虽然它仍然不看我像它会做什么明智的。我也不理解外部循环的目的,它将一个指针与一个字符进行比较。