2 つのプロセスの間のパイプは、親プロセスで作成されているファイルのペアです。パイプは、親プロセスがフォークしたときの結果のプロセスを接続します。パイプは、ファイル名空間には存在しないため、「匿名」と言います。パイプは通常、2 つのプロセスだけを接続しますが、任意の数の子プロセスを相互に、または親プロセスと 1 つのパイプだけで接続することもできます。
パイプは、親プロセスで pipe(2) 呼び出しを使用し作成されます。pipe(2) は 引数の配列に 2 つのファイル記述子を戻します。フォーク後、両方のプロセスは p[0] を使用して読み取り、p[1] を使用して書き込みます。プロセスは、実際にはそれらのために管理されている循環バッファとの間で読み取りと書き込みを行います。
fork(2) を使用すると、プロセスごとの開かれているファイルのテーブルが複写されるので、各プロセスは 2 つのリーダと 2 つのライタを持ちます。パイプを適切に機能させるには、余分なリーダとライタを閉じなければなりません。たとえば、同じプロセスによる書き込みのためにもう一方のリーダの終わりも開いていると、ファイルの終わりの指標は戻されません。次のコードは、パイプの作成、フォーク、および重複したパイプの終わりのクリアを示しています。
#include <stdio.h> #include <unistd.h> ... int p[2]; ... if (pipe(p) == -1) exit(1); switch( fork() ) { case 0: /* in child */ close( p[0] ); dup2( p[1], 1); close P[1] ); exec( ... ); exit(1); default: /* in parent */ close( p[1] ); dup2( P[0], 0 ); close( p[0] ); break; } ... |
表 7-1 は、一定の条件下でのパイプからの読み取りとパイプへの書き込みの結果を示しています。
表 7-1 パイプでの読み取りと書き込みの結果
実行 |
条件 |
結果 |
---|---|---|
読み取り |
空のパイプ、ライタ接続 |
読み取りはブロッキングされる |
書き込み |
フルのパイプ、ライタ接続 |
書き込みはブロッキングされる |
読み取り |
空のパイプ、接続ライタなし |
EOF が戻される |
書き込み |
リーダなし |
SIGPIPE |
fcntl(2) を記述子に呼び出して FNDELAY を設定すると、ブロッキングを阻止できます。この状態で入出力関数の呼び出しを行うと、errno に EWOULDBLOCK が設定され、エラー (-1) が戻されます。