存在するこのページ~から4.4 BSDオペレーティングシステムの設計と実装、それは言う:
パイプとソケットの主な違いは、パイプが通信チャネルを確立するために共通の親プロセスを必要とすることです。
ただし、正しく文書化した場合、新しいプロセスを作成する唯一の方法は、fork
既存のプロセスを作成することです。だから私は2つのプロセスが共通の祖先を持つことができない方法を理解していません。それでは、すべてのプロセスペアがパイプを介して互いに接続できることは正しいですか?
答え1
それでは、すべてのプロセスペアがパイプを介して互いに接続できることは正しいですか?
まさか。
パイプは親プロセスによって設定する必要があります。今後1 つ以上の子がフォークされます。子プロセスが分岐すると、そのファイル記述子は「外部から」(デバッガなどを無視)操作できず、親プロセス(または他のプロセス)は事実の後に「comms.channel設定」部分を実行できません。
したがって、すでに実行されている2つのランダムプロセスを使用している場合は、それらの間にパイプを直接設定することはできません。通信を許可するには、任意の形式のソケット(または他のIPCメカニズム)を使用する必要があります。 (ただし、一部のオペレーティングシステム(そのうちFreeBSD)では、Unixドメインソケットからファイル記述子を送信できます。)
答え2
この文はあまり明確ではありません。まず、親しなければならない先祖、パイプを設定するプロセスは、親プロセス、祖父母、曾祖父…祖父母または通信プロセスのいずれかである可能性があるためです。第二に、この文の意味は「パイプを望むなら共通祖先プロセスがなければならない」というのではなく、「パイプを望むならこれを設定する共通祖先プロセスがなければならない」ということです。
内部的には、プロセスは独自にパイプを設定します。パイプは、他のファイル記述子と同じファイル記述子、またはより正確には両端に1つずつあるファイル記述子のペアです。パイプを作成したプロセスはパイプをすぐに使用して自分にデータを送信できますが、これはほとんど役に立ちません。自己管理用途があります。)
一般的なイディオムは、プロセスがパイプを設定し、サブプロセスを分岐し、親プロセスでパイプの一端を閉じ、サブプロセスでパイプのもう一方の端を閉じることです。これにより、親プロセスと子プロセスが一方向に通信できます。プロセスに双方向通信が必要な場合は、2つのパイプが必要です(パイプが双方向の一部のUNIXバリエーションを除く)。
パイプは子プロセスによって継承されるため、パイプを作成したプロセスは通信に参加しない可能性があります。たとえば、2 つの外部コマンド間で生成されるシェルのパイプラインには、ls | rot13
次の手順が含まれます。
- シェルはパイプを生成します。
- シェルはプロセスを分岐します。子プロセスはパイプの読み取り端を閉じて
execve
を呼び出しますls
。 - シェルはプロセスを分岐します。子プロセスはパイプの書き込み端を閉じて
execve
を呼び出しますrot13
。 - シェルはパイプの両端を閉じ、両方の子プロセスが終了するのを待ちます。
2 つの既存のプロセスが互いに通信したい場合は、次のものを使用できます。名前付きパイプ。 (まあ、それもあります。ファイル記述子を渡すしかし、心が弱い人には適していません。 )
答え3
パイプのシェルは、パイプの複数のメンバー間で通信チャネルを確立する共通の親です。
すべてのプロセスは他のプロセスにパイプすることができます。唯一のプロセス役に立つ標準入力から読み出し、標準出力に書き込む「フィルタ」が一緒にパイプに接続されます。
たとえば、次のコマンドを実行すると
$ tail -f /etc/motd | tail -f | cat > /dev/null
ps -eaH
呼び出しシェルの子として猫と猫の2つの尾を表示します。
1675 pts/0 00:00:00 bash
2483 pts/0 00:00:00 tail
2484 pts/0 00:00:00 tail
2485 pts/0 00:00:00 cat