パイプを使用してサブシェルとstdoutの動作を理解する

パイプを使用してサブシェルとstdoutの動作を理解する

.cstdinからいくつかの入力を受け取り、次のようにその実行可能ファイルに入力を提供するファイルとその実行可能ファイル(fooと仮定)があるとします/bin/sh

python -c "<some script to feed input>" | ./foo

私はfooが呼び出したシェルがすぐに閉じてfooが終了することを観察しました。しかし、IRCの誰かが次のように提案しました。

(python -c "<some script to feed input>"; cat) | ./foo

呼び出されたサブシェルを./foo実行し続けます。ここで何が起こっているのだろうか。

私の推測:最初の場合、Pythonスクリプトのstdoutが完了するとすぐに終了し、./foo終了プロセスのstdinにEOFを送信します./fooか?しかし、システムコールはブロックコールと見なされて./foo終了しないので、これは私には理解できません。誤解を解決するための助けとリソースに関するアドバイスを聞きたいです。ありがとうございます!

ベストアンサー1

「EOF送信」のようなものはありません。読み取るデータがない場合は、ファイルの終わりに到達します。

最初のコードスニペットでPythonスクリプトが終了すると、パイプを開いているプロセスがなくなりました。したがって、fooパイプに送信されたすべてのデータを読み取ると、標準入力がファイルの終了条件を検出します。

2番目のコードスニペットでPythonスクリプトが終了すると、パイプはまだサブシェルによって開かれます。したがって、fooPythonスクリプトで生成されたすべてのデータを読み取った後も、追加の入力を待ち続けます。cat独自の標準入力からデータを読み取って渡すサブシェルが起動します。終了すると、cat状況は以前と同じです。どのプロセスも書き込みを行うためにパイプを開けず、foo入力端に到達します。

プロセスがreadシステムコール内でブロックされると、システムコールが返される可能性がある理由はいくつかあります。

  • データが利用可能な場合は、read正の値が返され、そのデータに渡されたバッファに対応するバイトが格納されます。
  • ファイルの終わりに達するとread0が返されます。通常のファイルの場合、ファイルの場所がファイルの終わりに達すると、これが発生します。パイプの場合、これはファイルを開いた最後のプロセスが終了し、パイプのバッファが完全に消費されたときに発生します。
  • エラーが発生するとread-1 が返されます。

おすすめ記事