私は2つの単純なプログラムを持っています:A
とB
。 A
が最初に実行され、次にB
がA
の「stdout」を取得して、その「stdin」として使用します。私がGNU/Linuxオペレーティングシステムを使用していて、これを行う最も簡単な方法は次のようになると仮定します。
./A | ./B
このコマンドについて説明する必要がある場合、それはプロデューサー(A
)から入力(つまり、読み取り)を受け取り、コンシューマー(B
)に書き込むコマンドであると言えます。それは正しい説明ですか?何か不足していますか?
間違ったとして目立つ質問についての唯一のことは、あなたが言うことです
Aが最初に実行され、次にBがAの標準出力を取得します。
実際、どちらのプログラムもほぼ同時に開始されます。 B
への入力がない場合、読み取ろうとすると、読み取る入力があるまでブロックされます。同様に、A
から出力を読み取る人がいない場合、その書き込みは、出力が読み取られるまでブロックされます(一部はパイプによってバッファーされます)。
パイプラインに参加するプロセスを同期する唯一のものは、I/O、つまりパイプを介した読み取りと書き込みです。書き込みまたは読み取りが発生しない場合、2つのプロセスは互いに完全に独立して実行されます。一方が他方の読み取りまたは書き込みを無視した場合、無視されたプロセスはブロックされ、最終的にSIGPIPE
信号(書き込みの場合)によって強制終了されるか、その標準入力ストリームでファイル終了条件が取得されます(読み取りの場合) )他のプロセスが終了したとき。
A | B
を記述する慣用的な方法は、2つのプログラムを含むパイプラインであるということです。最初のプログラムからの標準出力で生成された出力は、2番目のプログラムによって標準入力で読み取ることができます( "[の出力] A
は、[入力の] B
にパイプされます" )。シェルは、これを可能にするために必要な配管を行います。
「コンシューマー」と「プロデューサー」という言葉を使いたいのであれば、それも問題ないと思います。
これらがCで書かれたプログラムであることは関係ありません。これがLinux、macOS、OpenBSD、AIXであるという事実は関係ありません。
ドキュメントで通常使用される用語は、1つ以上のコマンドで構成される「パイプライン」です POSIX定義を参照してください つまり、技術的に言えば、2つのコマンド、つまりシェルの2つのサブプロセスです。 (fork()+exec()
'ed外部コマンドまたはサブシェル)
producer-consumer 部分に関しては、パイプラインはそのパターンで記述できます。
/proc/<pid>/fd
ディレクトリをチェックしている場合を除く)。stdout
に書き込み、コンシューマーはstdin
を単一のコマンドが実行されているかのように読み取り、別名 はお互いに存在しなくても存在できます 。ここで私が見る違いは、他の言語のProducer-Consumerとは異なり、シェルコマンドはバッファリングを使用し、バッファーがいっぱいになるとstdoutを書き込むということですが、Producer-Consumerはそのルールに従う必要があるという言及はありません-キューがいっぱいになるか破棄されるときだけ待つデータ(これはパイプラインが実行しない他のものです)。