Linux fifo(命名管道)O_NONBLOCK断开管道



我一直在用C++为linux编写一个使用进程间通信的小程序。我在尝试用一个进程以非阻塞的方式读取和用另一个进程写入(阻塞)时遇到了问题。问题看起来是这样的,当父级尝试用O_NONBLOCK(或O_NDELAY)读取管道时,它从不读取单个字节,而当子级尝试在管道上写入时,它失败了,并发送SIGPIPE管道断开信号。以下是代码示例:

// Parent process
mkfifo(PROC_COPROC, 0666);
int fd_co = open(PROC_COPROC, O_RDONLY | O_NDELAY);
char c;
int n;
fcntl(fd_co,F_SETFL,0); //fix it
while ((n = read(fd_co, &c, 1)) > 0)
{
    printf("%c", c);
}
close(fd_co);
// Child process
int fd = open(PROC_COPROC, O_WRONLY | O_APPEND);
if ( fd != -1 ) 
{
    write( fd , "messagen" , 8); //Fails here if flag not set
}
else
    printf("Ne peut pas ecrire sur le fifon");
close(fd);

我终于找到了一种方法来解决这个问题,在非阻塞开放调用之后立即使用fcntl(fd_co,F_SETFL,0);

在阅读了手册页之后,我找不到任何(简单)的解释,如果我想读取非阻塞和写入阻塞,为什么我必须重置文件描述符的标志。

有人有解释吗?还是我做错了?

O_NDELAY的"问题"是,当没有可用数据时,读取返回-1并将errno设置为EAGAIN。因此,您必须测试-1和errno的read的返回值,然后再次读取。

您的"修复"只是重置O_NDELAY,如果FIFO中没有可读取的内容,它会再次生成读取块。

另见read

返回值
…出现错误时,返回-1,并正确设置errno。

错误
EAGAIN文件描述符fd指的是套接字以外的文件,并且具有被标记为非阻塞(O_NONBLOCK),并且读取将阻塞
EAGAINEWOULDBLOCK
文件描述符fd引用了一个套接字,并已标记非阻塞(O_NONBLOCK),并且读取将阻塞。职位.1-2001允许在这种情况下返回任何一个错误,而不需要这些常量具有相同的值,因此是一个可移植的应用程序应该检查这两种可能性。

如果阻塞在您的情况下是一个问题,您也可以考虑使用select或@BasileStarynkevitch建议的poll

最新更新