破損したパイプによってUnixプロセスが終了する原因は何ですか?

破損したパイプによってUnixプロセスが終了する原因は何ですか?

気に入ったいくつかのオプションは次のとおりです。どちらが正しいかわからない。

  1. パイプからの読み込み中にI / Oエラーが発生しました。
  2. パイプのもう一方の端に書き込むプロセスは失敗で終了します。
  3. パイプに書き込むことができるすべてのプロセスがパイプを閉じました。
  4. パイプの書き込みバッファがいっぱいです。
  5. ピアがデュアルパイプの別の方向を閉じました。
  6. パイプから読み取ることができるプロセスがないため、書き込みは失敗します。
  7. システムコールが EPIPE エラーを返し、エラーハンドラがインストールされていません。

答え1

プロセスは、残りのリーダーを持たないタイプ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の読み取りを受け取り、この時点でyesSIGPIPEを受け取ります。

上記では、ほとんどのシェルはpipe(2)whileをksh93使用しsocketpair(2)ますが、これに関して動作は同じです。

プロセスがSIGPIPEを無視すると、書き込みシステム呼び出し(通常はwrite、、pwrite... sendspliceがエラーを返しますEPIPE。したがって、破損したパイプを手動で処理しようとするプロセスは、SIGPIPEを無視し、EPIPEエラーに対して対処することがよくあります。

答え2

(6)

パイプから読み取ることができるプロセスがないため、書き込みは失敗します。

記述子をコピーして分岐しないと、1つのプロセスしか開始できませんが、通常、パイプにはリーダーとライターがあり、どちらかが接続を閉じるとパイプは無効になります。名前付きパイプを使用している場合は、複数の接続(シリアル)を持つことができますが、この意味では、各接続は新しいパイプを表します。したがって、スレッドまたはプロセスの「パイプ」はファイル記述子と同義語です。

からman 7 pipe

パイプの読み取りの終わりを参照するすべてのファイル記述子が閉じられた場合、write(2)は呼び出しプロセスに対してSIGPIPE信号が生成されるようにします。呼び出しプロセスがこのシグナルを無視すると、write(2)はエラーEPIPEで失敗します。

したがって、「壊れたパイプ」は、著者にEOFが読者にあるのと同じです。

答え3

パイプ破損は、書き込みプロセスの前に読み取りプロセスが終了したときに発生します。だから私は(6)を選択します。

関連情報