2017-06-05 67 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) 

...雖然它仍然不看我像它會做什麼明智的。我也不理解外部循環的目的,它將一個指針與一個字符進行比較。