Сделайте, чтобы ReadFile () возвратился, как только что-то было прочитано - PullRequest
0 голосов
/ 08 января 2019

Я хочу последовательно читать данные с последовательного порта как в 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() вести себя как read() в Linux, т.е. возвращать, как только есть хотя бы 1 байт, даже если запрошено 256?

1 Ответ

0 голосов
/ 08 января 2019

IMO лучший подход - реализовать циклический буфер, использовать функции, которые вам нравятся, чтобы прочитать 1 байт из места потока в буфере, а затем вызвать функцию обратного вызова приема - или просто опросить циклический буфер на наличие данных.

Это решит все ваши проблемы - вы будете уведомлены (или вы можете опросить наличие данных), когда данные поступят, и не будут перезаписывать буфер (конечно, вам нужно прочитать данные в противном случае, если буфер заполнен) вы будете игнорировать новые данные)

Здесь у вас очень простая реализация

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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...