是什么使Unix进程死于管道中断?


30

这是我想到的一些选项,不确定哪个是正确的。

  1. 从管道读取I / O错误。
  2. 写入管道另一端的进程因失败而终止。
  3. 可以写入管道的所有进程均已将其关闭。
  4. 管道的写缓冲区已满。
  5. 对等方已关闭双工管道的另一方向。
  6. 写入失败,因为没有可以从管道读取的进程。
  7. 系统调用返回了EPIPE错误,并且没有安装错误处理程序。

你有什么问题?您是在问哪一个是正确的,或者是否还有其他因素会导致管道破裂?
AugustBitTony

@EightBitTony以下哪项是正确的
siamii

Answers:


38

当进程尝试写入没有剩余读取器的SOCK_STREAM类型的管道(命名或未命名)或套接字时,它会收到SIGPIPE。

通常是想要的行为。一个典型的例子是:

find . | head -n 1

find一旦head终止,您就不希望继续运行(然后关闭打开的唯一文件描述符以在该管道上读取)。

yes命令通常依赖于该信号来终止。

yes | some-command

将写入“ y”,直到某些命令终止。

请注意,这不仅是命令退出时,还是所有读取器都已将其读取fd关闭到管道时。在:

yes | ( sleep 1; exec <&-; ps -fC yes)
      1 2       1        0

在子外壳显式关闭其stdin之后,将从管道中读取1(子外壳),然后是2(子外壳+睡眠),然后是1(子外壳),然后是0 fd,此时yes将接收SIGPIPE。

上面,大多数shell使用pipe(2)一会儿ksh93使用socketpair(2),但是在这方面的行为是相同的。

当一个进程忽略SIGPIPE,书写系统调用(一般write,但可能是pwritesendsplice...)返回一个EPIPE错误。因此,想要手动处理断开管道的进程通常会忽略SIGPIPE并针对EPIPE错误采取措施。


14

(6)

写入失败,因为没有可以从管道读取的进程。

尽管除非重复描述符和派生,否则只能有一个过程开始:通常,管道具有一个读取器和一个写入器,并且当其中一个关闭连接时,该管道将被取消。如果您使用的是命名管道,则可以与其建立多个连接(串行连接),但是每个连接代表一种新的管道。因此,指向线程或进程的“管道”与文件描述符同义。

来自man 7 pipe

如果所有引用管道读取端的文件描述符都已关闭,则write(2)将导致为调用过程生成SIGPIPE信号。如果调用过程忽略此信号,则write(2)失败,并显示错误EPIPE。

因此,对于作者而言,“折断的管道”对读者而言就是EOF。


0

当读取过程在写入过程之前退出时,管道破裂。所以我会选择(6)


2
可以有多个读取或写入管道的进程,而相同的进程可以是读取和写入。另外,这与退出无关,而与关闭文件描述符有关。
斯特凡Chazelas
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.