通过线程之间的环(循环)缓冲区发送消息(在C中)

时间:2017-06-05 10:01:15

标签: c windows winapi circular-buffer

我需要使用WinAPI和Ring Buffer从主线程向我创建的线程发送消息。

我为Ring缓冲区定义了结构并编写了函数。 环形缓冲区 - 它包含头部,尾部,大小和指向结构描述符的指针,它具有数据长度和数据本身。由于我需要向CreateThread函数发送2个参数,因此我创建了第三个结构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;

我已经实现了Ring Buffer功能:

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;
}

我的主要:我检查过我可以发送几个字节(内存在线程之间共享),现在我需要通过Ring Buffer发送一条大消息(> BUFF_SIZE),而我正在尝试做什么( )循环。这是一个问题:我应该怎么做?我的东西不起作用,因为我在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 个答案:

答案 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)

......虽然它仍然不会让我觉得它会做任何明智的事情。我也不理解外部循环的目的,它将指针与字符进行比较。

答案 1 :(得分: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;
}