ICode9

精准搜索请尝试: 精确搜索
首页 > 系统相关> 文章详细

linux – 打开命名管道进行编写并在select()中使用它

2019-07-08 17:52:00  阅读:642  来源: 互联网

标签:linux select nonblocking named-pipes fifo


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

所以,我想打开一个用于编写的命名管道,并且需要以某种方式将它提供给select(),以便select()仅在命名管道的另一端有一个读取器时返回.

通常情况下,如果没有读卡器,则打开电话已挂起;不幸的是,我不能给select()打开一个动作 – 只有打开的文件描述符是有效的.

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

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返回为ready-to-write,即使没有连接读取器:

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.

这应该让你绕过虚拟黑客.然而,使用带有select()的fd,我认为是非首发.您可以使用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.

…通过在调用之前将global设置为true而在SIGPIPE处理程序中将false设置为false以指示没有读取器.

但是,Python可能是一个问题,因为你应该已经获得了这个信号,但显然不是.这可能是因为虚假黑客(你真的必须摆脱它).

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

请注意,一旦您因读卡器断开而达到EOF,您必须重新打开管道.不要继续使用相同的fd.

如果可行,我会选择unix local socket而不是fifo.

标签:linux,select,nonblocking,named-pipes,fifo
来源: https://codeday.me/bug/20190708/1404201.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有