使用select()和O_NONBLOCK从FIFO读取两次连续写入

时间:2016-04-23 02:44:17

标签: c select named-pipes nonblocking fifo

我正在尝试写两个连续的字符串。问题是读者在阅读器上使用O_NONBLOCK时会继续问候EAGAIN。

在使用O_NONBLOCK时,为什么它不起作用的任何想法都不应该select()处理块?

reader.c

#include <fcntl.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>

int main() {
    int fd;
    char * myfifo = "/tmp/myfifo";

    mkfifo(myfifo, 0666);
    fd = open(myfifo, O_RDWR | O_NONBLOCK);

    write(fd, "12345678", strlen("12345678"));
    write(fd, "HelloWorld", strlen("HelloWorld"));
    close(fd);

    return 0;
}

writer.c

#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdint.h>

char buf[BUFSIZ] = { 0 }, buf2[BUFSIZ] = { 0 };
int read1 = 0, read2 = 0;

int main() {
    int fd = 0, a = 0, b = 0 ; 
    char *myfifo= "/tmp/myfifo";

    mkfifo(myfifo, 0666);
    fd_set set;

    if ((fd = open(myfifo, O_RDWR | O_NONBLOCK)) < 0)
        exit(1);

    while (1) {
        FD_ZERO(&set);
        FD_SET(fd, &set);

        if ((select(fd+1, &set, NULL, NULL, NULL)) < 1)
            exit(1);

        if (FD_ISSET(fd, &set)) {
            int total = 0;

            if ((total = read(fd, buf + read1, sizeof(uint32_t) * 2) - read1) <= 0) {
                fprintf(stderr, "%s\n", strerror(errno));
                continue;
            }   
            read1 += total;

            if ((total = read(fd, buf2 + read2, BUFSIZ - read2)) <= 0) {
                fprintf(stderr, "%s\n", strerror(errno));
                continue;
            }   
            read2 += total;

            fprintf(stderr, "%s %d, %d, %s\n", buf, a, b, buf2);
            memset(buf, 0, BUFSIZ);
            memset(buf2, 0, BUFSIZ);
            read1 = read2 = 0;
        }   
    }   

    return 0;
}

1 个答案:

答案 0 :(得分:0)

您在循环中两次调用fd上的read,第一个read可能会读取可用数据,第二个read将失败{{1} }。 在执行任何EAGAIN之前,您应该使用select来测试准备情况,而不仅仅是第一个。{1}}。因为fifos是流,这意味着,你必须保持自己的不同数据边界。

read

另外,建议打开char buf[BUFSIZ]; if (FD_ISSET(fd, &set)) { int total = 0; int off = 0; total = read(fd, buf, sizeof buf); if (total <= 0) { fprintf(stderr, "%s\n", strerror(errno)); continue; } // retrieve the data based on how many bytes you have read if (total >= sizeof(uint32_t) * 2) { ... } } 表示读取结束,O_RDONLY表示结尾处写作结束。