ここに私が考えたいくつかのオプションがありますが、どちらが正しいのかわかりません。
プロセスは、(名前の有無にかかわらず)パイプまたはリーダーが残っていないタイプ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
_
1(サブシェル)、次に2(サブシェル+スリープ)、次に1(サブシェル)、その後0で、サブシェルが明示的にstdinを閉じた後にパイプからfdを読み取ります。そのとき、yes
がSIGPIPEを受け取ります。 。
上記では、ほとんどのシェルはpipe(2)
を使用していますが、_ksh93
_はsocketpair(2)
を使用していますが、動作は同じです。
プロセスがSIGPIPEを無視すると、書き込みシステムコール(通常はwrite
ですが、pwrite
、send
、splice
...の場合もあります)は、 EPIPE
エラー。そのため、壊れたパイプを手動で処理するプロセスは、通常、SIGPIPEを無視し、EPIPEエラー時にアクションを実行します。
(6)
パイプから読み取ることができるプロセスがないため、書き込みに失敗しました。
記述子とフォークを複製しない限り、最初に開始できるプロセスは1つだけです。通常、パイプには1つのリーダーと1つのライターがあり、そのうちの1つが接続を閉じると、パイプは無効になります。名前付きパイプを使用している場合、複数の接続を(シリアルで)作成できますが、それぞれがこの意味で新しいパイプを表します。したがって、スレッドまたはプロセスへの「パイプ」は、ファイル記述子と同義です。
man 7 pipe
から:
パイプの読み取り側を参照するすべてのファイル記述子が閉じられている場合、write(2)により、呼び出しプロセスに対してSIGPIPEシグナルが生成されます。呼び出しプロセスがこのシグナルを無視している場合、write(2)はエラーEPIPEで失敗します。
したがって、「壊れたパイプ」は、ライターにとってEOFがリーダーにとって何であるかです。
書き込みプロセスの前に読み取りプロセスが終了すると、パイプが壊れます。だから私は(6)で行きます