How do I perform a non-blocking fopen on a named pipe (mkfifo)?
如果我有一个程序创建并尝试使用mkfifo打开命名管道,那么如何打开管道以进行读取或写入而不会阻塞?
具体地说,我正在编写一个可以在有或没有gui(用Java编写)的情况下运行的C程序。
在C程序中,我使用mkfifo成功创建了命名管道,但是当我这样做时
1
| FILE * in = fopen(PIPE_IN ,"r"); /* Where PIPE_IN is the filename*/ |
fopen在GUI打开该管道进行写入之前不会返回。我想做的是让该管道准备好被读取一次(如果GUI决定将其写入)-我将把文件描述符放入select()调用中。可以合理预期Java GUI可能永远不会启动,因此我不能依靠它在任何特定点甚至根本不打开管道的另一端。
我还将打开第二个管道进行写入,并且我想我也会遇到同样的问题。此外,我无法在没有读取器的输出管道上设置O_NONBLOCK。
有什么建议吗?
(在Linux系统上运行)
- 在select()在输入管道上触发之前,是否需要打开输出管道?
-
@tinkertim-我想从技术上讲不是-我已经在设置函数中设置了它们,但是我可以先设置输出管道,然后再调用select,为什么?
您可以open()您的管道O_RDONLY | O_NONBLOCK,如果需要C流,则可以使用fdopen()获得它。但是,select()-AFAIK可能存在问题,为读取打开的管道fd总是没有准备好读取器,并且read()返回0,因此select()会无限期触发。
一种克服此问题的笨拙方法是打开管道O_RDWR;也就是说,至少要有一个编写器(您的C程序)。无论如何,这将解决您的问题。
- 麻烦读者了-但我不能在输出管道上设置O_NONBLOCK ...
-
POSIX标准说(的select()):"当调用O_NONBLOCK清除的输入函数的调用不会阻塞时,无论该函数是否成功传输数据,都应认为描述符已准备就绪,可以读取。" (POSIX.1:2008)。
-
当程序读取(或写入)时,打开管道O_RDWR将导致死锁-除非在打开管道的情况下实际上还有另一个进程。
-
@Jonathan Leffler-但是我可以打开它的RDWR并只是对其进行轮询以查看何时实际写入了另一个进程吗?那不应该造成僵局,对吗?
-
是的,这应该在select()中阻塞。对于管道的写端没有这样的解决方案,可能最好的办法是在收到Java程序的提示后打开写端
-
@jpalecek是的,我意识到昨晚我不得不思考Tinkertim为何在原始问题的评论中询问顺序之后要做的事情。