0

我一直在使用进程间通信在 C++ 中为 linux 编写一个小程序。我在尝试以非阻塞方式读取一个进程并使用另一个进程写入(阻塞)时遇到问题。问题看起来像这样,当父级尝试使用O_NONBLOCK(or 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 , "message\n" , 8); //Fails here if flag not set
}
else
    printf("Ne peut pas ecrire sur le fifo\n");
close(fd);

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

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

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

4

1 回答 1

4

O_NDELAY 的“问题”是,当没有可用数据时, read 返回-1并将 errno 设置为。所以,你必须测试for和 errnoEAGAIN的返回值,然后再读取。read-1

您的“修复”只是重置 O_NDELAY,如果没有从 FIFO 中读取的内容,它会再次阻止读取。

也可以看看read

返回值
... 出错时,返回 -1,并适当设置 errno。

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

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

于 2013-02-17T18:51:14.683 回答