2013-02-17 180 views
0

我一直在使用进程间通信在Linux上为C++编写一个小程序。当尝试以一种非阻塞的方式读取一个进程并使用另一个进程写入(阻塞)时,我遇到了问题。问题看起来像这样,当父母试图用O_NONBLOCK(或O_NDELAY)读取管道时,它从不读取单个字节,并且当孩子试图在管道上写入时,管道将失败并发送破损的管道信号。下面是代码示例:Linux fifo(命名管道)O_NONBLOCK中断管道

// 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);来解决这个问题。

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

任何人有解释或我做错了吗?

+0

你确定管道的两端都打开(读写)吗? – Erwald 2013-02-17 17:46:02

回答

3

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

您的“修复”只是重置O_NDELAY,如果没有什么要从FIFO中读取,它会再次读取块。

read

返回值
见......上的错误,则返回-1,并且errno设置为合适。

ERRORS
EAGAIN文件描述符fd是指除套接字之外的文件,并且具有 有了明显的非阻塞(O_NONBLOCK),并将所读取的将阻塞。
EAGAINEWOULDBLOCK
文件描述符fd是指一种插座和已被标记 非阻塞(O_NONBLOCK),并将所读取的将阻塞。 POSIX.1-2001 允许为这种情况返回任何错误,并且这些常量不需要 具有相同的值,因此便携式应用程序 应检查两种可能性。

您还可以考虑使用select,或poll作为@BasileStarynkevitch建议,如果阻塞是在你的情况的问题。

+0

我建议使用'poll'而不是'select' – 2013-02-17 19:03:38

+0

你是对的,我错过了那个细节。由于读取是在一个循环中完成的,我通过打开文件描述符read |来修复它在循环之前的noblock并关闭它之后。这样,读取结束被打开,一旦写入结束打开并开始发送数据,它就会读取。谢谢! – 2013-02-17 19:49:50