什么情况会导致一个已打开、非阻塞的命名管道(FIFO)无法进行读取?

13
抱歉,我只能使用英语进行回答。
new_pipe = os.open(pipe_path, os.O_RDONLY | os.O_NONBLOCK) # pipe_path points to a FIFO
data = os.read(new_pipe, 1024)

读取时偶尔会引发 errno -11: 资源暂时不可用。

在什么情况下会引发此错误?看起来非常罕见,因为通常情况下会返回数据:

  • 如果没有写入器打开管道,则返回空字符串('')。
  • 如果写入器已经打开了管道,但是 fifo 中没有任何数据,也会返回空字符串('')。
  • 当然,如果写入器向 fifo 中放入数据,则可以读取该数据。

可能是[sendto:资源暂时不可用(errno 11)]的重复问题(https://dev59.com/KFbTa4cB1Zd3GeqP-m0n)。 - agf
@agf:另一个问题是关于sendto出错,这是因为发送缓冲区已满。与这个特定问题的联系最好是可疑的,因为我们在这里谈论的是Unix管道的读取。 - Niklas B.
@NiklasB。这个问题确实不相似,但答案是相同的。将其视为重复并投票关闭只是一种方便的方式,可以链接到其他问题,并将其链接到侧边栏的顶部。 - agf
1个回答

12
POSIX规范中的read系统调用(我强调)中获取:

当尝试从空管道或FIFO读取时:

  • 如果没有进程打开该管道进行写操作,则read()应返回0以表示文件结束。

  • 如果某个进程打开了该管道进行写操作,并且设置了O_NONBLOCK,read()应返回-1并将errno设置为[EAGAIN]。

所以,基本上您的第二个假设是错误的:

如果写入器已经打开了管道,但fifo中没有数据,则还会返回空字符串('')

这将违反规范,而且我无法在我的计算机上重现这种行为(它对我引发了EAGAIN)。然而,这不是一个大问题,您可以捕获异常并重试:

import errno

def safe_read(fd, size=1024):
   ''' reads data from a pipe and returns `None` on EAGAIN '''
   try:
      return os.read(fd, size)
   except OSError, exc:
      if exc.errno == errno.EAGAIN:
         return None
      raise

非常感谢。看起来我自己的测试代码确实有错误! - UsAaR33

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接