ホームに戻る
出典 :
関連 :
目次 :
パイプ(無名パイプ)
あるプログラムの出力を別プログラムの入力として使用するための仕組み。プロセス間通信の手法の一つである。
語源である「パイプライン」と呼ばれたり、後述の「名前付きパイプ」と区別するために「無名パイプ」とも呼ばれる。
発祥であるUNIXおよびUnix系OSの特徴であった。Windowsにも同様の機構が実装されている。
パイプの特徴(利点)
パイプによって連結された各プログラムは前のプログラムの終了を待たずに開始する(マルチタスク)ため、
特にプログラムのオーバーヘッドが重い場合に威力を発揮する。
また、パイプを用いたデータの受け渡しは主記憶(メモリ)上で完結し、補助記憶を消費しない。
シェル(コマンドライン)での使用
最も一般的なパイプの用途である。" | "(バーティカルバー)はシェルに対してパイプを指示する演算子で、
それぞれのプログラムの出力は次のプログラムの入力として渡される。
grep 札幌市 Address.txt | a2ps | lpr
上記のコマンドは、Address.txt から "札幌市" という文字列を検索し、その結果を a2ps で整形、その結果を印刷するという処理である。
a2ps および lpr は直前のプログラムの終了を待たずに開始(並列実行)されるため、順次実行するよりもパフォーマンスが高い。
パイプを使用しない場合との比較
grep 札幌市 Address.txt > sapporo.txt
a2ps < sapporo.txt > print.ps
lpr < print.ps
上記の例ではパイプを使用せず、中間ファイルを用いてデータを受け渡している。
これはパイプを用いた場合よりも記述が冗長であるだけでなく、マルチタスクの恩恵を受けられないため処理が遅くなる。
さらに、中間ファイルを用いることで補助記憶を消費するとともに、ファイル読み書きのコストも発生する。
UNIXにおける哲学
一連の入出力、データのやり取りを一つのプログラム内で完結しようとするとプログラムが肥大化・複雑化し、バグを誘発するとともに保守性が悪化する。
そこで、「一つだけの仕事をする道具のようなソフトウェア」をパイプラインによって組み合わせることで複雑な処理を実現するという発想が生まれた。
それぞれの処理を行うプログラムは小さくて単純なため、整備・再利用が容易である。
但し、ユーザは役割(道具)ごとに処理させるデータを分割する必要がある。
(パイプの使用を前提とした「構造設計」を行う必要がある。)
名前付きパイプ
上述のパイプを拡張したもの。UNIXおよびUnix系とWindowsで使用可能であるが、意味合いは異なる。
UNIX / Unix系
上述の無名パイプがシェルを用いるのに対し、名前付きパイプはファイルシステムを使用する。
mkfifo()
またはmknod()
で明示的に作成された名前付きパイプに、二つのプロセスのうち一方は書き手、他方は読み手としてアクセスする。
ファイルシステムを介してはいるが、一時ファイルを作成するわけではなく、無名パイプと同様データの授受は主記憶上で完結する。
尚、mkfifo
はコマンドとしても存在する。
例
名前付きパイプ( my_pipe )を作成し、パイプに入力されたものをgzipで圧縮する。
mkfifo my_pipe
gzip -9 -c < my_pipe > out.gz &
注意が必要な点
UNIX / Unix系の名前付きパイプはそれを作成したプロセスによらず永続的であるため、役目を終えた時点で削除する必要がある。
(無名パイプは入口、および出口プロセスが動作中のみ存在し、それらが終了した際に自動的に破棄される。
そもそも名前付きパイプはそれを使用するプロセスを特定できない。)
Windows
Windowsにおける名前付きパイプはクライアントサーバ型通信に供することを想定されており、
サーバアプリケーションで用いる「受動」(受信待ち)モードを備えている。
ファイルシステム上に作成され、ファイルと同様にアクセスすることができる。
名前付きパイプが専用のファイルシステム(Named Pipe FileSystem - NPFS)上に作成される点、
また無名パイプと同様に永続性が無く、そのパイプをオープンしているプロセスが存在しなくなると自動的に消滅する点がUnix系と異なる。
名前付きパイプはNPFSのルートディレクトリに置かれ、\\.\pipe\
という専用のパスにマウントされる。
例えば、my_pipe
という名前付きパイプのパスは \\.\pipe\my_pipe
となる。
実装例
出典元を参照。