检测器何时关闭命名管道(FIFO)

时间:2015-02-04 07:08:28

标签: linux named-pipes

作者是否有办法知道读者已经关闭了命名管道(或已退出)的末尾,没有写入它?

我需要知道这一点,因为我写入管道的初始数据是不同的;读者期望在其余数据到来之前有一个初始标题。

目前,当write()EPIPE失败时,我会检测到此情况。然后我设置一个标记,表示"下次,发送标题"。但是,在我写完任何东西之前,读者可以关闭并重新打开管道。在这种情况下,我从来没有意识到他做了什么,也没有发送他所期待的标题。

是否有任何类型的异步事件类型可能对此有帮助?我没有看到任何信号被发送。

请注意,我还没有包含任何语言标记,因为这个问题应该被视为与语言无关。我的代码是Python,但答案应该适用于C或任何其他具有系统调用级绑定的语言。

3 个答案:

答案 0 :(得分:3)

如果您使用的是基于poll系统调用的事件循环,则可以使用包含EPOLLERR的事件掩码注册管道。在Python中,使用select.poll

import select
fd = open("pipe", "w")
poller = select.poll()
poller.register(fd, select.POLLERR)
poller.poll()

将等到管道关闭。

要对此进行测试,请运行mkfifo pipe,启动脚本,然后在另一个终端运行中运行,例如cat pipe。一旦退出cat进程,脚本就会终止。

答案 1 :(得分:3)

奇怪的是,当最后一个阅读器关闭管道时,select表示管道是可读的:

<强> writer.py

#!/usr/bin/env python
import os
import select
import time

NAME = 'fifo2'

os.mkfifo(NAME)


def select_test(fd, r=True, w=True, x=True):
    rset = [fd] if r else []
    wset = [fd] if w else []
    xset = [fd] if x else []

    t0 = time.time()
    r,w,x = select.select(rset, wset, xset)

    print 'After {0} sec:'.format(time.time() - t0)
    if fd in r: print ' {0} is readable'.format(fd)
    if fd in w: print ' {0} is writable'.format(fd)
    if fd in x: print ' {0} is exceptional'.format(fd)

try:
    fd = os.open(NAME, os.O_WRONLY)
    print '{0} opened for writing'.format(NAME)

    print 'select 1'
    select_test(fd)

    os.write(fd, 'test')
    print 'wrote data'

    print 'select 2'
    select_test(fd)

    print 'select 3 (no write)'
    select_test(fd, w=False)

finally:
    os.unlink(NAME)

<强>演示:

1号航站楼:

$ ./pipe_example_simple.py
fifo2 opened for writing
select 1
After 1.59740447998e-05 sec:
 3 is writable
wrote data
select 2
After 2.86102294922e-06 sec:
 3 is writable
select 3 (no write)
After 2.15910816193 sec:
 3 is readable

2号航站楼:

$ cat fifo2
test
# (wait a sec, then Ctrl+C)

答案 2 :(得分:1)

没有这样的机制。通常,根据UNIX方式,两端都没有流打开或关闭的信号。这只能通过读或写(相应)来检测。

我会说这是错误的设计。目前,您正尝试通过打开管道让接收器发出接收信号。因此,要么以适当的方式实现此信令,要么合并&#34;关闭逻辑&#34;在管道的发送部分。