从linux vs OS X中的命名管道读取 [英] reading from named pipes in linux vs OS X

查看:123
本文介绍了从linux vs OS X中的命名管道读取的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

下面的程序在OS X下可以正常运行,但在Linux下则不能.它继续循环遍历perror("read error")行,读取缓冲区中没有字节,并且EWOULDBLOCK不是errno(errno = 0);

The program below works well under OS X but not in linux. It continues to loop through the perror("read error") line, with no bytes in the read buffer, and EWOULDBLOCK isn't the errno (errno=0);

在OS X中,该程序按预期方式工作,即它从三个命名管道中读取,并将其中任何数据打印到控制台.

In OS X the program works as expected, which is that it reads from three named pipes, and prints any data from any of them to the console.

        #include <sys/types.h>
        #include <sys/select.h>
        #include <sys/time.h>
        #include <sys/types.h>
        #include <errno.h>
        #include <stdlib.h>
        #include <stdio.h>
        #include <fcntl.h>
        #include <unistd.h>


        int readPipe(int fd)
        {
            ssize_t bytes;
            size_t total_bytes = 0;
            char buffer[100*1024];

            printf("\nReading pipe descriptor # %d\n",fd);
            for(;;) {
                bytes = read(fd, buffer, sizeof(buffer));
                if (bytes > 0) {
                    total_bytes += (size_t)bytes;
                    printf("%s", buffer);
                } 
                else {
                    if (errno == EWOULDBLOCK) {
                        break; // recieve buffer is empty so return to main loop
                    } 
                    else {
                        perror("read error"); 
                        return EXIT_FAILURE;
                    }
                }
            }
            return EXIT_SUCCESS;
        }


        int main(int argc, char* argv[])
        {
            int fd_a, fd_b, fd_c;   // file descriptors for each pipe
            int nfd;                // select() return value
            fd_set read_fds;        // file descriptor read flags
            struct timeval tv;
            tv.tv_sec = 0;
            tv.tv_usec = 10000;

            // create pipes to monitor (if they don't already exist)
            system("mkfifo /tmp/PIPE_A");
            system("mkfifo /tmp/PIPE_B");
            system("mkfifo /tmp/PIPE_C");
            system("chmod 666 /tmp/PIPE_*");

            // open file descriptors of named pipes to watch
            fd_a = open("/tmp/PIPE_A", O_RDONLY | O_NONBLOCK); // the O_RDWR flag is undefined on a FIFO.
            if (fd_a == -1) {
                perror("open error");
                return EXIT_FAILURE;
            }

            fd_b = open("/tmp/PIPE_B", O_RDONLY | O_NONBLOCK);
            if (fd_b == -1) {
                perror("open error");
                return EXIT_FAILURE;
            }

            fd_c = open("/tmp/PIPE_C", O_RDONLY | O_NONBLOCK);
            if (fd_c == -1) {
                perror("open error");
                return EXIT_FAILURE;
            }

            // check for new data in each of the pipes
            for(;;)
            {
                // clear fds read flags
                FD_ZERO(&read_fds);

                // PIPE_A
                FD_SET(fd_a, &read_fds);
                nfd = select(fd_a+1, &read_fds, NULL, NULL, &tv);
                if (nfd != 0) {
                    if (nfd == -1) {
                        perror("select error");
                        return EXIT_FAILURE;
                    }
                    if (FD_ISSET(fd_a, &read_fds)) {
                        readPipe(fd_a);
                    }
                }

                // PIPE_B
                FD_SET(fd_b, &read_fds);
                nfd = select(fd_b+1, &read_fds, NULL, NULL, &tv);
                if (nfd != 0) {
                    if (nfd == -1) {
                        perror("select error");
                        return EXIT_FAILURE;
                    }
                    if (FD_ISSET(fd_b, &read_fds)){
                        readPipe(fd_b);
                    }
                }

                // PIPE_C
                FD_SET(fd_c, &read_fds);
                nfd = select(fd_c+1, &read_fds, NULL, NULL, &tv);
                if (nfd != 0) {
                    if (nfd == -1) {
                        perror("select error");
                        return EXIT_FAILURE;
                    }
                    if (FD_ISSET(fd_c, &read_fds)){
                        readPipe(fd_c);
                    }
                }
            }
            return EXIT_SUCCESS;
        }

推荐答案

允许(并且预期)读取可以返回0.这意味着管道正在返回EOF.您没有处理此情况.除非调用失败并返回-1,否则errno的内容无关紧要.

It is allowable (and expected) that read can return 0. This means the pipe is returning EOF. You are not handling this condition. The contents of errno are irrelevant unless the call fails and returns -1.

for (;;)
{
    bytes = read(fd, buffer, sizeof(buffer));

    if (bytes > 0)
    {
        total_bytes += (size_t)bytes;
        printf("%s", buffer);
    }

    if (bytes == 0)
        return //something appropriate

    if (bytes == -1)
    {
        if (errno == EWOULDBLOCK)
           break; // recieve buffer is empty so return to main loop
        else
        {
            perror("read error");
            return EXIT_FAILURE;
        }
    }
}

您正在努力返回不同的代码,但是您在main中没有对它们进行任何注意.

You are going through the effort to return different codes but you don't pay any attention to them in main.

此外,这3条select语句又是什么?我认为在上一个问题中已经解决了这一问题.

Also, what's with the 3 select statements again? I thought that was cleared up in a previous question.

修改

for (;;)
{
    // clear fds read flags
    FD_ZERO(&read_fds);
    FD_SET(fd_a, &read_fds);
    FD_SET(fd_b, &read_fds);
    FD_SET(fd_c, &read_fds);

    tv.tv_sec = 0;
    tv.tv_usec = 10000;

    nfd = select(fd_c + 1, &read_fds, NULL, NULL, &tv);

    if (nfd == 0) //timeout - continue or do something else for a bit
        continue;

    if (nfd == -1)
    {
        perror("select error");
        return EXIT_FAILURE;
    }

    if (FD_ISSET(fd_a, &read_fds))
        readPipe(fd_a);

    if (FD_ISSET(fd_b, &read_fds))
        readPipe(fd_b);

    if (FD_ISSET(fd_c, &read_fds))
        readPipe(fd_c);
}

这篇关于从linux vs OS X中的命名管道读取的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆