Answers:
当进程尝试写入没有剩余读取器的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
,但可能是pwrite
,send
,splice
...)返回一个EPIPE
错误。因此,想要手动处理断开管道的进程通常会忽略SIGPIPE并针对EPIPE错误采取措施。
(6)
写入失败,因为没有可以从管道读取的进程。
尽管除非重复描述符和派生,否则只能有一个过程开始:通常,管道具有一个读取器和一个写入器,并且当其中一个关闭连接时,该管道将被取消。如果您使用的是命名管道,则可以与其建立多个连接(串行连接),但是每个连接代表一种新的管道。因此,指向线程或进程的“管道”与文件描述符同义。
来自man 7 pipe
:
如果所有引用管道读取端的文件描述符都已关闭,则write(2)将导致为调用过程生成SIGPIPE信号。如果调用过程忽略此信号,则write(2)失败,并显示错误EPIPE。
因此,对于作者而言,“折断的管道”对读者而言就是EOF。