パイプライン (Unix)

フリー百科事典ウィキペディアより
ナビゲーションにジャンプ 検索にジャンプ
テキスト端末で実行される 3 つのプログラム プロセスのパイプライン

Unix ライクなコンピュータオペレーティング システムではパイプラインはメッセージ パッシングを使用したプロセス間通信のメカニズムです。パイプラインは、各プロセスの出力テキスト ( stdout ) が入力 ( stdin )として次のプロセスに直接渡されるように、標準ストリームによってチェーン化された一連のプロセスです。2 番目のプロセスは、最初のプロセスがまだ実行されているときに開始され、同時に実行されます。パイプラインの概念は、Unix の祖先である Bell Labs の Douglas McIlroy によって提唱さまし、Unix の開発中に、そのツールボックスの哲学を形成しました。[1] [2]物理的なパイプラインに例えると、名前が付けられます。これらのパイプラインの重要な特徴は、「内部を隠す」ことです (Ritchie & Thompson, 1974)。これにより、システムがより明確でシンプルになります。

この記事は匿名パイプに関するもので、あるプロセスによって書き込まれたデータは、次のプロセスによって読み取られるまでオペレーティング システムによってバッファリングされます。この単方向チャネルは、プロセスが完了すると消えます。これは、名前付きパイプとは異なります。名前付きパイプでは、メッセージは、ファイルにすることによって名前が付けられたパイプとの間でやり取りされ、プロセスが完了した後も残ります。無名パイプの標準シェル構文は、複数のコマンドを縦棒で区切ってリストすることです (一般的な Unix の言い回しでは「パイプ」)。

コマンド1 | コマンド2 | コマンド3

たとえば、現在のディレクトリ内のファイルを一覧表示し ( ls )、文字列"key"を含むls出力の行のみを保持し( grep )、結果をスクロール ページに表示するには ( less )、ユーザーは次のように端末のコマンドライン:

ls -l | grep キー| 以下

コマンドls -lはプロセスとして実行され、その出力 (stdout) はプロセスの入力 (stdin) にパイプされgrep keyます。のプロセスについても同様ですlessプロセスは、前のプロセスから入力を取得し、標準ストリームを介して次のプロセスの出力を生成し ますそれぞれが、オペレーティング システムに実装されている(匿名) パイプと呼ばれるプロセス間通信メカニズム|によって、左側のコマンドの標準出力を右側のコマンドの標準入力に接続するようにシェルに指示します。パイプは単方向です。データはパイプラインを左から右に流れます。

以下は、 URLで示されるWebリソースの一種のスペル チェッカーを実装するパイプラインの例ですそれが何をするかの説明は次のとおりです。

curl "https://en.wikipedia.org/wiki/Pipeline_(Unix)"  | 
sed 's/[^a-zA-Z]//g'  | 
tr 'AZ '  'az\n'  | 
grep '[az]'  | 
並べ替え -u | 
comm -23 - < ( sort /usr/share/dict/words )  |
以下
  1. curlWeb ページのHTMLコンテンツを取得します (wget一部のシステムで使用できます)。
  2. sedスペースまたは文字以外の (Web ページのコンテンツからの) すべての文字をスペースに置き換えます。(改行は保持されます。)
  3. trすべての大文字を小文字に変更し、テキスト行のスペースを改行に変換します (各「単語」は別の行になりました)。
  4. grep少なくとも 1 つの小文字のアルファベット文字を含む行のみが含まれます (空白行は削除されます)。
  5. sort「単語」のリストをアルファベット順にソートし、-uスイッチは重複を削除します。
  6. comm2 つのファイル間で共通する行を検索-23し、2 番目のファイルに固有の行と両方に共通する行を抑制し、最初に指定されたファイルでのみ見つかった行のみを残します。-ファイル名の代わりに、標準comm入力 (この場合はパイプラインから) を使用します。予想どおり、ファイルの内容をアルファベット順にsort /usr/share/dict/wordsソートし、結果を (プロセス置換を介して)読み取る一時ファイルに出力します。結果は、/usr/share/dict/words に見つからない単語 (行) のリストです。wordscomm<( ... )comm
  7. lessユーザーが結果をページングできるようにします。

コマンドライン インターフェイスのパイプライン

広く使用されているすべての Unix シェルには、パイプラインを作成するための特別な構文構造があります。すべての使用法において、 ASCII 垂直バー文字|(このため、「パイプ文字」と呼ばれることが多い)で区切られたコマンドを順番に記述します。シェルはプロセスを開始し、標準ストリーム間の必要な接続を手配します (ある程度のバッファーストレージを含む)。

エラーストリーム

デフォルトでは、パイプライン内のプロセスの標準エラー ストリーム(" stderr ") はパイプを介して渡されません。代わりに、それらはマージされてコンソールに送信されます。ただし、多くのシェルには、この動作を変更するための追加の構文があります。たとえば、csh シェルでは、代わりに使用する|&|標準エラー ストリームも標準出力とマージされ、次のプロセスに供給される必要があることを意味します。Bashシェルは|&、バージョン 4.0 以降[3]または を使用して標準エラーをマージしたり2>&1、別のファイルにリダイレクトしたりすることもできます。

パイプミル

最も一般的に使用される単純なパイプラインでは、シェルはパイプを介して一連のサブプロセスを接続し、各サブプロセス内で外部コマンドを実行します。したがって、シェル自体は、パイプラインを流れるデータを直接処理することはありません。

ただし、いわゆるミルまたはパイプミルを使用して、シェルが直接処理を実行することは可能です(whileコマンドは、最初のコマンドの結果を「ミル処理」するために使用されるため)。このコンストラクトは通常、次のようになります。

コマンド |  while  read -r var1 var2 ... ;  do 
    # var1、var2 などに解析された変数を使用して、各行を処理します
    # (これはサブシェルである可能性があることに注意してください: var1、var2 などは
    # while ループが終了した後は利用できなくなります; zsh や新しいシェルなどの一部のシェル
    # Korn シェルのバージョンでは、パイプ
    # 演算子の左側のコマンドをサブシェルで処理します)
    完了

[ 4]catループの最初の繰り返しで、そのようなプログラム ( drainと呼びましょう) は から残りの出力を読み取りsshます。その後、ループは終了します (結果はドレインの詳細に依存します)。この動作を回避するには、いくつかの方法があります。まず、一部のドレーンは、からの読み取りを無効にするオプションをサポートしています(例: )。あるいは、何か役に立つことを行うためにドレインがからの入力を読み取る必要がない場合は、それを入力として与えることができます。 stdincommandstdinssh -nstdin< /dev/null

パイプのすべてのコンポーネントが並行して実行されるため、シェルは通常、サブプロセス (サブシェル) をフォークしてその内容を処理し、変数の変更を外部のシェル環境に伝達することを不可能にします。この問題を解決するために、代わりにコマンド置換を含むヒア ドキュメントから「pipemill」を供給することができます。これは、パイプラインの実行が終了するのを待ってからコンテンツを処理します。または、名前付きパイプまたはプロセス置換を使用して並列実行することもできます。GNU bashには、最後のパイプ コンポーネントのフォークを無効にするオプションもあります。[5]lastpipe

プログラムによるパイプラインの作成

パイプラインは、プログラム制御下で作成できます。Unixpipe() システム コールは、オペレーティング システムに新しい無名パイプオブジェクトを作成するように要求します。これにより、プロセス内に 2 つの新しいファイル記述子 (パイプの読み取り専用エンドと書き込み専用エンド) が作成されます。パイプの端は、シーク機能がないことを除けば、 通常の匿名のファイル記述子のように見えます。

デッドロックを回避して並列処理を利用するために、1 つまたは複数の新しいパイプを持つ Unix プロセスは、通常、fork()新しいプロセスを作成するために呼び出します。各プロセスは、データを生成または消費する前に、使用しないパイプの端を閉じます。または、プロセスが新しいスレッドを作成し、パイプを使用してスレッド間で通信する場合もあります。

名前付きパイプmkfifo()は、 or使用して作成しmknod()、プログラムが呼び出されたときに入力ファイルまたは出力ファイルとしてプログラムに提示することもできます。マルチパス パイプを作成でき、標準のエラー リダイレクトや と組み合わせると特に効果的teeです。

実装

ほとんどの Unix ライクなシステムでは、パイプラインのすべてのプロセスが同時に開始され、ストリームが適切に接続され、マシン上で実行されている他のすべてのプロセスと共にスケジューラによって管理されます。Unixパイプを他のパイプ実装とは別に設定することの重要な側面は、バッファリングの概念です。たとえば、送信プログラムは毎秒5000バイトを生成する場合があります、受信プログラムは 1 秒あたり 100 バイトしか受け入れられない場合がありますが、データが失われることはありません。代わりに、送信側プログラムの出力がバッファーに保持されます。受信プログラムがデータを読み取る準備ができると、パイプライン内の次のプログラムがバッファから読み取ります。バッファーがいっぱいになると、受信者によって少なくとも一部のデータがバッファーから削除されるまで、送信プログラムは停止 (ブロック) されます。Linux では、バッファーのサイズは 65,536 バイト (64KiB) です。必要に応じて、 bfrと呼ばれるオープン ソースのサードパーティ製フィルターを使用して、より大きなバッファーを提供できます。

ネットワークパイプ

netcatsocatなどのツールは、パイプを TCP/IPソケットに接続できます。

歴史

パイプラインの概念はDouglas McIlroy [6]によって考案され、 Version 3 Unixのman ページ最初に説明されました[7] McIlroy は、多くの場合、コマンド シェルが、あるプログラムからの出力ファイルを別のプログラムへの入力として渡す ことに気付きました。

彼のアイデアは 1973 年に実装されました (「ある熱狂的な夜に」、McIlroy は書いています) Ken Thompsonpipe()がバージョン 3 Unix のシェルといくつかのユーティリティにシステム コールとパイプを追加しました。「次の日」とマキロイは続けた。McIlroy はまた、バージョン 4|でのパイプ構文の記述を大幅に簡素化した記法でThompson の功績を認めています[8] [7]

独立して開発されましたが、Unix パイプは1960 年代にKen Lochner [9]によってDartmouth Time Sharing Systemのために開発された「通信ファイル」に関連し、先行していました[10]

Tony Hoare の Communications Sequential Processes (CSP)では、McIlroy のパイプがさらに開発されています。[11]

AppleAutomatorのアイコンにあるロボットは、パイプラインの概念を使用して反復コマンドを連結し、元の Unix の概念に敬意を表してパイプを保持しています。

その他のオペレーティング システム

Unixのこの機能は、 MS-DOSVM/CMSおよびMVSのCMS パイプラインパッケージなどの他のオペレーティング システムに借用され、最終的にはソフトウェア エンジニアリングのパイプとフィルターの設計パターンに指定れるようになりました。

も参照

参考文献

  1. ^ Mahoney, Michael S. "The Unix Oral History Project: Release.0, The Beginning" . McIlroy: そこは、私が Unix の管理権限をほとんど握っていた数少ない場所の 1 つでした。そうです。
  2. ^ 「預言的なペトログリフ」 . cm.bell-labs.com . 1999 年 5 月 8 日のオリジナルからのアーカイブ2022年5月22日閲覧
  3. ^ "Bash リリース ノート" . tiswww.case.edu 2017 年 6月14 日閲覧
  4. ^ 「SSH とのシェル ループの相互作用」 . 2012 年 3 月 6 日。 2012 年 3 月 6 日に元の場所からアーカイブされました
  5. ^ ジョン1024. 「「find」コマンドの結果を配列として Bash に保存するにはどうすればよいですか」 . スタック オーバーフロー
  6. ^ 「UNIX オペレーティング システムの作成」 . ベル研究所。2004 年 9 月 14 日にオリジナルからアーカイブされました。
  7. ^ a b McIlroy, MD (1987). リサーチ Unix リーダー: Programmer's Manual, 1971–1986 (PDF) (Technical report)からの注釈付き抜粋。CSTR。ベル研究所。139。
  8. ^ http://www.linfo.org/pipe.htmlパイプ: The Linux Information Project (LINFO) による簡単な紹介
  9. ^ http://www.cs.rit.edu/~swm/history/DTSS.doc [裸の URL DOX/DOCX ファイル]
  10. ^ 「データ」 . cm.bell-labs.com . 1999 年 2 月 20 日のオリジナルからのアーカイブ2022年5月22日閲覧
  11. ^ https://swtch.com/~rsc/thread/ベル研究所と CSP スレッド (Russ Cox)

外部リンク