我的总体目标是将报告信息传递到命名pipe道,如果(并且只有)有读取器连接到该命名pipe道。 如果没有阅读器,我想避免构build报告信息等。由于这是发生在其他数据stream通过select()
处理的情况下,我想添加命名的pipe道到“准备写入”。
所以,我想打开一个命名pipe道进行写入,并且需要以select()
方式将其提供给select()
,以便在命名pipe道的另一端确实存在读取器的情况下,仅返回select()
。
通常,如果没有阅读器, open
呼叫已经挂起; 不幸的是,我不能给一个open
动作select()
– 只打开文件描述符是有效的。
为了得到一个体面的文件描述符,我正在创build一个虚拟阅读器(我打开命名pipe道阅读自己),然后打开写入,然后closures虚拟阅读器:
dummy = os.open(fifoPath, os.O_RDONLY | os.O_NONBLOCK) # ^^^ without the NONBLOCK, this will hang until another process is ready to write fifo = os.open(fifoPath os.O_WRONLY) os.close(dummy)
如果我现在打开另一个读者,他会收到我写入命名pipe道的内容,所以这方面正在工作。
但是现在select()
总是返回fifo
作为ready-to-write,即使没有阅读器连接:
r, w, e = select.select([], [ fifo ], []) print w[0]
这会一直打印fifo
值。
写入命名pipe道也不会挂起,不pipe我写了多less:
fifo.write('foo')
我写的数据只是丢失,因为没有阅读器连接。
当打开我的虚拟阅读器,我传递的标志O_NONBLOCK
,否则这个开放也挂起。 我试过各种方法,但无法弄清楚如何正确地做到这一点。
任何人都可以告诉我如何结合使用select()
写入命名pipe道?
(上面的代码是用Python编写的,但是我猜这个问题并没有真正连接到Python,而是一个Linux / Unix问题,所以我不会把这个问题标记为Python。)
请参阅man 7 fifo
WRT管道应如何工作。
进程可以在非阻塞模式下打开一个FIFO。 在这种情况下,即使没有人打开写入端,只读打开也会成功,除非另一端已经打开,打开只写入将失败,ENXIO(没有这样的设备或地址)。
在Linux下,打开一个用于读写的FIFO将在阻塞和非阻塞模式下成功。 这可以用来打开一个先进先出的写作,而没有读者可用。 使用连接的两端为了与自己进行通信的过程应该非常小心,以避免死锁。
这应该让你围绕dummy
黑客。 然而,使用fd与select()
,我认为是一个非起动器。 你可以改为使用select()
来简化超时,以便在主循环内间隔使用write()
select()
来轮询fd,利用事实…
当一个进程试图写入另一端没有打开的FIFO时,进程发送一个SIGPIPE信号。
…通过在SIGPIPE处理程序中调用和设置全局为true
来指示没有读者。
Python可能是一个问题,但是,因为你应该已经得到这个信号,但显然不是。 这可能是因为dummy
黑客(你真的不得不摆脱这一点)。
另一个也许更好的想法是为fifo分叉一个使用阻塞调用的处理程序,而且还维护管道描述符到主进程的正常配对(读/写)。 其中的一个(作者;即,由主进程读取)可以与select()
一起使用。 当读卡器连接时, open()
和主信号。
请注意,一旦因读取器断开而到达EOF, 您必须重新打开管道 。 不要继续使用相同的fd。
如果可能的话,我会选择一个超过fifo的unix本地套接字 。