Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/kotlin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 在linux与OS X中读取命名管道_C_Linux_Macos_Posix_Named Pipes - Fatal编程技术网

C 在linux与OS X中读取命名管道

C 在linux与OS X中读取命名管道,c,linux,macos,posix,named-pipes,C,Linux,Macos,Posix,Named Pipes,下面的程序在OSX下运行良好,但在linux下不起作用。它继续循环通过perror(“read error”)行,读取缓冲区中没有字节,并且eWoldBlock不是errno(errno=0) 在OSX中,程序按预期工作,即它从三个命名管道中读取数据,并将其中任何一个管道中的任何数据打印到控制台 #include <sys/types.h> #include <sys/select.h> #include <sys/t

下面的程序在OSX下运行良好,但在linux下不起作用。它继续循环通过perror(“read error”)行,读取缓冲区中没有字节,并且eWoldBlock不是errno(errno=0)

在OSX中,程序按预期工作,即它从三个命名管道中读取数据,并将其中任何一个管道中的任何数据打印到控制台

        #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;
        }
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
int读取管道(int fd)
{
ssize_t字节;
大小\u t总字节=0;
字符缓冲区[100*1024];
printf(“\n读取管道描述符#%d\n”,fd);
对于(;;){
字节=读取(fd,buffer,sizeof(buffer));
如果(字节>0){
总字节数+=(大小)字节数;
printf(“%s”,缓冲区);
} 
否则{
if(errno==ewoldblock){
break;//接收缓冲区为空,因此返回主循环
} 
否则{
perror(“读取错误”);
返回退出失败;
}
}
}
返回退出成功;
}
int main(int argc,char*argv[])
{
int fd_a,fd_b,fd_c;//每个管道的文件描述符
int nfd;//select()返回值
fd_set read_fds;//文件描述符读取标志
结构时间值电视;
tv.tv_sec=0;
tv.tv_usec=10000;
//创建要监视的管道(如果它们不存在)
系统(“mkfifo/tmp/PIPE_A”);
系统(“mkfifo/tmp/PIPE_B”);
系统(“mkfifo/tmp/PIPE_C”);
系统(“chmod 666/tmp/管道*”;
//打开要监视的命名管道的文件描述符
fd_a=open(“/tmp/PIPE_a”,O_RDONLY | O_NONBLOCK);//在FIFO上未定义O_RDWR标志。
如果(fd_a==-1){
perror(“公开错误”);
返回退出失败;
}
fd|b=打开(“/tmp/PIPE|b”,O|RDONLY | O|UNBLOCK);
如果(fd_b==-1){
perror(“公开错误”);
返回退出失败;
}
fd_c=打开(“/tmp/PIPE_c”,O_RDONLY | O_NONBLOCK);
如果(fd_c==-1){
perror(“公开错误”);
返回退出失败;
}
//检查每个管道中是否有新数据
对于(;;)
{
//清除fds读取标志
FD_零(&read_fds);
//管道
FD_集(FD_a和read_fds);
nfd=选择(fd_a+1和读取fds、NULL、NULL和tv);
如果(nfd!=0){
如果(nfd==-1){
perror(“选择错误”);
返回退出失败;
}
if(FD_ISSET(FD_a和读取fds)){
读取管(fd_a);
}
}
//管道
FD_集(FD_b和read_fds);
nfd=选择(fd_b+1和读取fds、NULL、NULL和tv);
如果(nfd!=0){
如果(nfd==-1){
perror(“选择错误”);
返回退出失败;
}
if(FD_ISSET(FD_b和读取fds)){
读取管道(fd_b);
}
}
//管道
FD_集(FD_c和read_fds);
nfd=选择(fd_c+1和读取fds、NULL、NULL和tv);
如果(nfd!=0){
如果(nfd==-1){
perror(“选择错误”);
返回退出失败;
}
if(FD_ISSET(FD_c和读取fds)){
读取管(fd_c);
}
}
}
返回退出成功;
}
允许(和预期)读取可以返回0。这意味着管道正在返回EOF。你没有处理这种情况。除非调用失败并返回-1,否则
errno
的内容不相关

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
中没有注意它们

另外,3个
select
语句又是怎么回事?我想在前面的问题中已经澄清了这一点

编辑

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

管道读取(tv.tv_usec)的超时应为0(对于两个操作系统)。感谢您的反馈。当errno=0时,正在读取的管道没有数据,这是预期的情况,因此退出_成功是合适的(我意识到在这个小示例程序中没有处理)。在linux中应用此更改,它仍然会循环执行readPipe调用(但在OSX中不会)。因此,如果在linux下删除printf()语句,它的性能会更好。关于三个选择,我减少了fd_集,但我认为仍然需要多个选择(我还没有找到一个模型或示例来说明我正在尝试做什么)。如果你能给我指一个,我将不胜感激!。不,那不太对。如果返回代码为0,则没有数据-事实上,管道的写入端已关闭。除非函数返回-1,否则Errno没有意义。除非调用失败,否则大多数调用不会设置errno。因此,在没有失败调用的情况下,errno中的任何内容都可以来自任何先前文件描述符上的任何先前调用。我基本上概述了您想对select执行的操作。我看到只有在所有三个FD都用于更新read_fds标志之后,才会调用FD_ISSET,然后最高的FD用于select。看起来不错,而且效率也更高。我还理解errno=0表示EOF(写入程序关闭)a