使用fifo以非阻塞模式打开并选择

我有两个进程A和B.通信流总是A – > B,但我需要使用命名管道来做,因为我必须在B进程内的select调用中使用管道文件描述符,并写入数据当任何或两个进程退出时,管道必须保持不变。

管道两端以非阻塞模式打开。 在过程A:

int push_fifo_fd = open(FIFO_NAME, O_WRONLY | O_NONBLOCK | O_CREAT, 0644); 

在流程B中:

 int fd = open(FIFO_NAME, O_RDONLY | O_NONBLOCK | O_CREAT, 0644); 

Q1。 进程B使用curl多接口,因此我得到curl多句柄的fd_sets并将“fd”描述符添加到读取fd_set,而不是调用select,以获取可用于读取和写入的文件描述符。 在每次调用select中,“fd”包含在结果读取fd_set中,但read返回0,即使写入结束也是如此。 这导致进程B使用100%的处理器时间。 我提到我不知道订购哪个管子的末端是打开的。 B的相关代码:

 while (1) { fd_set read_fds, write_fds, err_fds; FD_ZERO(&read_fds); FD_ZERO(&write_fds); FD_ZERO(&err_fds); FD_SET(fifo_fd, &read_fds); // some code ccode = curl_multi_fdset(curlm, &read_fds, &write_fds, &err_fds, &max_fd); max_fd = MAX(max_fd, fifo_fd); rc = select(max_fd + 1, &read_fds, &write_fds, &err_fds, &timeout); switch (rc) { case -1: WARN("select"); continue; case 0: default: { if (FD_ISSET(fifo_fd, &read_fds)) { // read from the fifo_fd } /* Now look at the handles that need attention */ int old_running_handles = running_handles; ccode = curl_multi_perform(curlm, &running_handles); if (ccode != CURLM_OK && ccode != CURLM_CALL_MULTI_PERFORM) { WARN("curl_multi_perform error: %s", curl_multi_strerror(ccode)); continue; } if (running_handles != old_running_handles) { CURLMsg *curl_msg; int left_msgs = 0; while ((curl_msg = curl_multi_info_read(curlm, &left_msgs)) != NULL) { // treat each easy handle } } } break; } } 

Q2。 在“man 7 fifo”中说“进程可以在非阻塞模式下打开FIFO。在这种情况下,即使在写入端没有打开任何人,只读打开也会成功,只写打开会失败使用ENXIO(没有这样的设备或地址),除非另一端已经打开。“ 但是进程A总是能够以非阻塞模式成功打开管道的写入端,即使读取端未打开。 这是为什么? 我测试的平台是Ubuntu服务器12.04.3,内核3.8.0-29。

因为:

在Linux下,打开FIFO进行读写将在阻塞和非阻塞模式下成功。 POSIX将此行为保留为未定义。 这可用于打开FIFO进行写入,而没有可用的读取器。 使用连接的两端以便与自身通信的进程应该非常小心以避免死锁。

来自http://linux.die.net/man/7/fifo

Q1 select()或者poll()期望Q1。 查看链接的问题 。 优雅的解决方案是在同一个fifo上打开另一个fd并关闭原始fd。

我相信在某些版本的内核中也会出现Q2。 男人7 fifo有一段关于它:

  Under Linux, opening a FIFO for read and write will succeed both in blocking and nonblocking mode. POSIX leaves this behavior undefined. This can be used to open a FIFO for writing while there are no readers available. 

该段似乎声称您可以随时成功打开fifo的写入结束,如原作者在Q2中所观察到的那样。

虽然它似乎与前一段相矛盾,因为原来的问题也是从男人7 fifo页面引用的,基本上说开放会失败而不是成功:

  A process can open a FIFO in nonblocking mode. In this case, opening for read-only succeeds even if no one has opened on the write side yet and opening for write-only fails with ENXIO (no such device or address) unless the other end has already been opened. 

我看到在4.9.37内核上读取端未打开时,非阻塞模式下的写入结束将会失败。 我猜,它必须已从3.8版更改为4.9版。