gpt4 book ai didi

linux - 打开命名管道进行写入,并在 select() 中使用

转载 作者:IT王子 更新时间:2023-10-29 00:40:42 25 4
gpt4 key购买 nike

我的总体目标是当(且仅当)有一个读取器连接到命名管道时,将报告信息传递到命名管道。如果没有阅读器,我想避免构建报告信息等。由于这是在通过 select() 处理其他数据流的场景中发生的,所以我想将命名管道添加到“准备好写入”的流。

所以,我想打开一个用于写入的命名管道,并且需要以某种方式将其提供给 select(),以便 select() 仅在存在的情况下返回实际上是命名管道另一端的读取器。

通常,如果没有阅读器,open 调用已经挂起;不幸的是,我无法为 select() 提供 open 操作——只有打开的文件描述符才有效。

为了获得合适的文件描述符,我目前正在创建一个虚拟阅读器(我自己打开命名管道进行读取),然后打开它进行写入,然后再次关闭虚拟阅读器:

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)

如果我现在打开另一个阅读器,他将收到我写入命名管道的内容,所以这方面是有效的。

但是现在 select() 总是返回准备好写入的 fifo,即使没有连接阅读器也是如此:

r, w, e = select.select([], [ fifo ], [])
print w[0]

这将始终并立即打印 fifo 值。

无论我写多少,写入命名管道也不会挂起:

fifo.write('foo')

我写入的数据刚刚丢失,因为没有连接阅读器。

当打开我的虚拟阅读器时,我传递了标志 O_NONBLOCK 因为否则这个打开也会挂起。我尝试了各种方法,但无法弄清楚如何正确执行此操作。

谁能告诉我如何使用 select() 组合写入命名管道?

(上面的代码是用 Python 写的,但我猜这个问题并不是真正与 Python 相关,而是一个 Linux/Unix 问题,所以我不会将这个问题标记为 Python。)

最佳答案

请参阅 man 7 fifo WRT 管道应如何以非阻塞方式工作。

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

Under Linux, opening a FIFO for read and write will succeed both in blocking and nonblocking mode. This can be used to open a FIFO for writing while there are no readers available. A process that uses both ends of the connection in order to communicate with itself should be very careful to avoid deadlocks.

这应该可以让您绕过 dummy hack。但是,我认为将 fd 与 select() 结合使用是行不通的。您可以使用 select() 的短超时来促进在主循环内每隔一段时间使用 write() 轮询 fd,利用以下事实......

When a process tries to write to a FIFO that is not opened for read on the other side, the process is sent a SIGPIPE signal.

...通过在调用前将全局变量设置为 true 并在 SIGPIPE 处理程序中将其设置为 false 以指示没有读取器。

不过,Python 在这里可能是个问题,因为您应该已经收到此信号,但显然没有。这可能是因为 dummy hack(你真的必须摆脱它)。

另一个也许更好的想法是为使用阻塞调用的 fifo 派生一个处理程序,但也维护一个正常的管道描述符对(读/写)到主进程。其中之一(写入器;即由主进程读取)可以与 select() 一起使用。 fork 等待 open() 并在读取器连接时向 main 发出信号。

请注意,一旦由于读取器断开连接而到达 EOF,您必须重新打开管道。不要继续使用相同的 fd。

如果可行的话,我会选择 unix local socket通过 fifo。

关于linux - 打开命名管道进行写入,并在 select() 中使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24887818/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com