PIPE †
- プロセス間通信の1つで、単方向通信手段を提供する。
多くは、forkした親と子プロセスの間で通信するようなケースで利用されることが多い。
- 名前は持たない、名前を持つものをFIFO(名前つきパイプ)と呼ぶ。
- データは、カーネル空間を経由してやりとりされる。
書式 †
#include <unisdt.h>
int pipe(int fildes[2]);
#include <fcntl.h>
int pipe2(int fildes[2], int flags);
pipeはファイルディスクリプタ(fd)のペアを作成する。引数には、ペアのfdを格納するint型の配列を指定する。0番目がend-of-read、1番目がwrite-endとなる。pipe関数でパイプを作成した後、forkでプロセスを生成すると、親子で共通のパイプを参照した状態となる。その後、例えば親側で0番をclose、子側で1番をcloseすれば、親から子への単方向のデータフローを実現することができる。
pipe2は、flagsを渡してファイルディスクリプタに関する属性を設定することができる。flagsが0の場合、pipeと同様となる。flagsに指定できる属性は以下である。
関連
int filedes[2];
// pipe
pipe(filedes);
fcntl(fildes[0], F_SETFL, O_NONBLOCK);
fcntl(fildes[1], F_SETFL, O_NONBLOCK);
fcntl(fildes[0], F_SETFD, FD_CLOEXEC);
fcntl(fildes[1], F_SETFD, FD_CLOEXEC);
// pipe2
pipe2(filedes, O_CLOEXEC | O_NONBLOCK);
read-endがcloseしている状態でwriteするとエラーで-1
が返る(SIGPIPE)。write-endがcloseしている状態でreadすると、0(EOF)
となる。
なお、パイプバッファのサイズは制限があり、パイプがfullの状態でwriteするとblockまたは失敗する。システムの実装によって異なるため注意。2.6.35以降では、サイズは16ページとなっている。また、fcntlで変更可能となっている。
参考 PIPE(7) - on http://man7.org/linux/man-pages/man7/pipe.7.html
返り値 †
成功時は0
を返す。失敗時は-1
を返し、errno
に以下の値がセットされる。
エラー †
- EFAULT
- EMFILE
- ENFILE
- システムでオープンされているファイル数が上限に達している
- ENOMEM
pipe2()
ソースサンプル †
親プロセスと子プロセスでpipeを経由して通信 †
実験 pipeごとのバッファ、パイプサイズの確認 †
利用例 †
PostgreSQLのpostmasterダウン検知 †
PostgreSQLでは、postmasterプロセスのダウン検知をpipeを使って実装している。子プロセスは、親プロセスのディスクリプタをチェックし、親プロセスの生死を確認している。以下はイメージソースである(大体イメージソースのようなことをしている)。
参考PostmasterIsAlive() - https://git.postgresql.org/gitweb/
参考リンク †