無名パイプ(ムメイパイプ)とは | 意味や読み方など丁寧でわかりやすい用語解説
無名パイプ(ムメイパイプ)の意味や読み方など、初心者にもわかりやすいように丁寧に解説しています。
読み方
日本語表記
むめいパイプ (ムーメイパイプ)
英語表記
anonymous pipe (アノニマスパイプ)
用語解説
無名パイプとは、プロセス間通信(IPC)の一種であり、主に親子関係にあるプロセス間でデータをやり取りするために使用される、一時的な単方向のデータストリームを指す。その名の通り、ファイルシステム上に名前を持たず、関連するプロセスが終了すると消滅する特徴がある。これは、異なるプログラム間で連携して処理を行う際に、一方のプログラムの出力をもう一方のプログラムの入力として渡すような場面で非常に有効な仕組みである。
詳細に入ると、無名パイプはオペレーティングシステム(OS)のカーネルによって管理されるメモリ上のバッファとして実装される。このバッファは、あるプロセスが書き込んだデータを別のプロセスが読み出すための通り道となる。パイプを作成すると、通常、読み込み用と書き込み用の二つのファイルディスクリプタ(ファイルやデバイスにアクセスするための識別子)が生成される。これは、まるで水道管の片側が読み込み口、もう片側が書き込み口になっているようなものと考えると分かりやすいかもしれない。
無名パイプの典型的な利用シナリオは、まず親プロセスがpipe()のようなシステムコールを呼び出してパイプを作成することから始まる。この時点では、親プロセスだけがパイプの読み込み用と書き込み用のファイルディスクリプタを持っている。次に、親プロセスがfork()システムコールを使って子プロセスを生成すると、子プロセスは親プロセスのファイルディスクリプタを複製して継承する。これにより、親プロセスと子プロセスが同じパイプにアクセスできる状態となる。
この状態で通信を確立するには、親と子のそれぞれが、自分が使うディスクリプタ(例えば親が書き込み用、子が読み込み用)以外の不要なディスクリプタを閉じる必要がある。もし両方のプロセスが読み込み用と書き込み用の両方を持っていても通信は可能だが、役割を明確にし、デッドロックやリソースリークを防ぐために、不要な側を閉じるのが一般的だ。例えば、親プロセスが子プロセスにデータを送りたい場合、親は書き込み用ディスクリプタだけを残して読み込み用を閉じ、子は読み込み用ディスクリプタだけを残して書き込み用を閉じる。これにより、親から子への単方向通信路が完成する。
パイプは単方向通信の特性を持つため、データを送りたい方向ごとにパイプを一つ用意する必要がある。つまり、親から子へ、子から親へ双方向に通信したい場合は、二つのパイプを作成することになる。
無名パイプにおけるデータの流れは、書き込み側がデータをパイプに書き込むと、そのデータはカーネルのバッファに一時的に蓄えられ、読み込み側がそのデータをパイプから読み出すことで消費される。ここで重要なのが「ブロック機構」である。もし読み込み側がパイプが空の状態でデータを読み出そうとすると、データが書き込まれるまで待機状態(ブロック)となる。逆に、書き込み側がパイプが満杯の状態でデータを書き込もうとすると、読み込み側がデータを消費するまで待機状態となる。このブロック機構により、データの生産速度と消費速度の差を吸収し、データの一貫性を保つことができる。
無名パイプの「無名」という特徴は、ファイルシステム上に特別なエントリ(名前)を持たないことを意味する。そのため、作成したプロセス(とその子プロセス)が存続している間だけ有効であり、関連する全てのファイルディスクリプタが閉じられると、OSによって自動的に破棄される。これは、一時的なデータ転送に特化しており、システム再起動時にはデータが失われる揮発性の性質も持つ。
この「無名」という特性は、設定や管理が簡単であるという利点をもたらす一方で、全く関係のないプロセス間での通信には不向きであるという制約も持つ。異なるプロセス間で通信を行うには、ファイルシステム上に名前を持つ「名前付きパイプ(FIFO)」や、共有メモリ、メッセージキューといった別のプロセス間通信の仕組みを用いる必要がある。
シェルコマンドのパイプライン処理は、無名パイプの最も身近な例だ。例えば、ls | grep .txtというコマンドを実行すると、lsコマンドの標準出力は無名パイプに接続され、そのパイプに書き込まれたデータ(ファイルリスト)をgrep .txtコマンドが標準入力として読み込み、.txtで終わるファイル名だけを抽出する。このように、複数のコマンドを連携させて一つのタスクを効率的に実行するために、無名パイプは不可欠な役割を担っている。