一旦读取某些内容,使ReadFile()返回

时间:2019-01-08 15:42:11

标签: c winapi serial-port

我想在Linux和Windows上以一致的方式从串行端口读取数据。我注意到read()ReadFile()的行为略有不同。考虑以下代码:

// on Linux
int r = read(fd, buf, 256);

// on Windows
ReadFile(handle, buf, 256, &r, NULL);

这两个函数将永远阻塞直到数据到达。到目前为止,一切都很好。但是,有一点区别:read()将在至少1个字节到达时立即返回,而ReadFile()在所有256个字节到达之前不会返回。

因此,我想问:是否有一种方法可以使ReadFile()像Linux上的read()一样,即即使请求了256个字节,只要有至少1个字节就返回?

1 个答案:

答案 0 :(得分:0)

IMO最好的方法是实现循环缓冲区,使用您喜欢的函数从缓冲区中的流位置读取1个字节,然后调用receive回调函数-或仅轮询循环缓冲区以获取数据。

它可以解决所有问题-当数据到达时,您会收到通知(或可以轮询存在的数据),并且不会覆盖缓冲区(当然,如果缓冲区已满,则需要读取数据)您将忽略新数据)

这里您有一个非常简单的实现

unsigned char buff[128];

struct 
{
    unsigned head:8;
    unsigned tail:8;
}control = {.head = 0, .tail = 0};

int isFull(void)
{
    return (control.head + 1) == control.tail;
}

int isEmpty()
{
    return control.head == control.tail;    
}

int push(int ch)
{
    if(!isFull())
    {
        buff[control.head++] = ch;
        return 0;
    }
    return -1;
}

int pop(void)
{
    if(!isEmpty())
    {
        return buff[control.tail++];
    }
    return -1;
}

简单用法

void (*rcvcallback)(void);
initReceive(void (*callback)(void))
{
    rcvcallback = callback;
}

void receive(void)
{
    int r = 0;

    #ifdef LINUX
    read(fd, &r, 1);
    #endif

    #ifdef WINDOWS
    size_t size;
    ReadFile(handle, &r, 1, &size, NULL);
    #endif

    push(r);
    rcvcallback();
}

#ifdef WINDOWS
#define EL "\n\r"
#endif
#ifdef LINUX
#define EL "\n"
#endif


void myRCVcallback(void)
{
    printf("Byte received: %d"EL, pop());
}


int main()
{
    printf("Starting ......"EL);

    while(1)
    {
        receive();
    }

    return 0;
}