web-dev-qa-db-ja.com

2つのプロセスを相互にパイプできますか?

このページ from4.4BSDオペレーティングシステムの設計と実装では、次のように述べられています。

パイプとソケットの主な違いは、パイプは通信チャネルを設定するために共通の親プロセスを必要とすることです

ただし、正しく記録した場合、新しいプロセスを作成する唯一の方法は、既存のプロセスをforkすることです。そのため、2つのプロセスが共通の祖先を持つことができなかった方法を実際に確認することはできません。それでは、プロセスの任意のペアを相互にパイプできると考えるのは正しいでしょうか?

8
qdii

それでは、プロセスの任意のペアを相互にパイプできると考えるのは正しいでしょうか?

あんまり。

パイプは親プロセスで設定する必要がありますbefore子プロセスがフォークされます。子プロセスがフォークされると、そのファイル記述子は「外部から」(デバッガーなどを無視して)操作できなくなり、親(または他のプロセス)は事後に「通信チャネルのセットアップ」部分を実行できなくなります。 。

したがって、すでに実行されている2つのランダムプロセスを取得する場合、それらの間に直接パイプを設定することはできません。それらを通信させるには、何らかの形式のソケット(または別のIPCメカニズム)を使用する必要があります(ただし、一部のオペレーティングシステム(FreeBSDなど)では、Unixでファイル記述子を送信できます-ドメインソケット。)

7
Mat

その文はあまり明確ではありません。まず、パイプを設定するプロセスとして、parentancestorである必要があります親、祖父母、祖父母、祖父母、または通信プロセスの1つにすることができます。第二に、この文は「パイプが必要な場合は共通の祖先プロセスが存在する必要がある」という意味ではなく、「パイプが必要な場合は共通の祖先プロセスがそれを設定する必要がある」という意味です。

内部では、プロセスはそれ自体とのパイプを確立します。パイプは、他と同様のファイル記述子、またはより正確には両端に1つずつのファイル記述子のペアです。パイプを作成したプロセスは、パイプをすぐに使用してデータを自分自身に送信できますが、これが役立つことはめったにありません(ただし、 self-pipe は使用されます)。

典型的なイディオムは、プロセスがパイプをセットアップしてから子プロセスをフォークし、パイプの一方の端を親で閉じ、もう一方の端を子で閉じることです。これにより、親プロセスと子プロセスが一方向で通信できるようになります。プロセスが双方向通信を必要とする場合、2つのパイプが必要です(パイプが双方向である一部のUNIXバリアントを除く)。

パイプはすべての子に順番に継承されるため、パイプを作成したプロセスが通信に関与していない可能性があります。たとえば、ls | rot13などの2つの外部コマンドの間に作成されたシェル内のパイプには、次の手順が含まれます。

  • シェルはパイプを作成します。
  • シェルはプロセスをフォークします。子はパイプの読み取り側を閉じ、execvelsで呼び出します。
  • シェルはプロセスをフォークします。子はパイプの書き込み終了を閉じ、rot13execveを呼び出します。
  • シェルはパイプの両端を閉じ、両方のサブプロセスが終了するのを待ちます。

2つの既存のプロセスが互いに通信したい場合、それらは 名前付きパイプ を使用できます。 (まあ、 ファイル記述子の受け渡し もありますが、それは気弱な人向けではありません。)

パイプラインのシェルは、パイプラインの複数のメンバー間に通信チャネルを設定する共通の親です。

どのプロセスも他のプロセスにパイプできます。 便利に使用できるで一緒にパイプ処理される唯一のプロセスは、stdinから読み取り、stdoutに書き込む「フィルター」です。

たとえば、コマンドを発行した場合

$ 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
2
msw