web-dev-qa-db-ja.com

パイプを使用したサブシェルと標準出力の動作の理解

.cファイルとそれに対応する実行可能ファイル(fooとしましょう)があり、stdinから入力を受け取り、/bin/shをsys呼び出しするとします。次のように、この実行可能ファイルに入力をフィードします。

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

Fooによって呼び出されたシェルがすぐに閉じて、fooが終了することを確認しました。ただし、IRCの誰かが、次のように実行することをお勧めします。

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

./fooによって呼び出されたサブシェルを引き続き実行します。ここで何が起こっているのか知りたいのですが。

私の推測:最初のケースでは、pythonスクリプトのstdoutは、完了するとすぐに閉じますか?したがって、EOFをプロセスのstdinに送信します./foo終了./foo?しかし、sys呼び出しは、./fooが終了しない原因となるブロック呼び出しである必要があるため、私には意味がありません。誤った理解を修正するためのヘルプとリソースへのポインタをいただければ幸いです。 。ありがとう!

2
iart

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

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

2番目のスニペットでは、Pythonスクリプトが終了すると、パイプはサブシェルによって開いたままになります。したがって、fooがPythonスクリプトによって生成されたすべてのデータの読み取りを終了した場合でも、それはさらに入力を待ち続けます。サブシェルはcatを起動します。これは、独自の標準入力からデータを読み取って転送します。 catが終了すると、状況は以前と同じになります。書き込み用にパイプを開いているプロセスはなくなり、fooは入力の最後に到達します。

readシステムコールでプロセスがブロックされた場合、そのシステムコールが返される理由はいくつかあります。

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