打开命名pipe道用于写入并在select()中使用它

我的总体目标是将报告信息传递到命名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本地套接字 。