web-dev-qa-db-ja.com

Unixパイプの正確な創意工夫は何ですか

ダグラス・マックロイがこのコンセプトを思いついた方法とケン・トンプソンが一晩でそれを実装した方法の話を聞いたことがあります。

私が理解している限り、パイプは、1つのプロセスが書き込みを行い、他のプロセスが読み取りを行う2つのプロセス間でメモリの一部を共有するシステムコールです。

OSの内部や概念に詳しくない人として、ストーリーの「天才」とは一体何なのだろうと思っていました。 2つのプロセスがメモリを共有するという考えですか?それとも実装ですか?または両方?

PS:パイプの有用性やシェルでの使用方法を知っています。問題は、|のコンセプトと実装についてです

53
aoak

私が理解している限り、パイプは、1つのプロセスが書き込みを行い、他のプロセスが読み取りを行う2つのプロセス間でメモリの一部を共有するシステムコールです。

実際には、関連する共有メモリはありません。リーダーとライターはアドレス空間のどの部分も共有しておらず、明示的な同期を使用していません。

読み取りおよび書き込みプロセスは、readおよびwriteシステムコールexactlyをファイルからの読み取りまたはファイルへの書き込みと同じように実行しています。それが天才です...イノベーション:(単純な)プロセス間通信とファイルI/Oが同じ方法で処理できるという概念...アプリケーションプログラマーとユーザーの観点から。

パイプが設定されると、OS(アプリケーションコードやユーザー空間のライブラリではない)がバッファリングと調整を処理します。透明に。


対照的に、パイプの概念が発明される前は、「パイプライン」処理を行う必要がある場合、通常、1つのアプリケーションがファイルに出力を書き込み、それが終了したら、2番目のアプリケーションを実行してファイル。

または、真のパイプラインが必要な場合は、両方のアプリケーションをコーディングして(実際の)共有メモリセグメントをセットアップし、セマフォ(または何か)を使用して読み取り/書き込みを調整できます。複雑な...そしてその結果として頻繁に行われません。

109
Stephen C

私の意見では、「パイプ」のアイデアの天才は、使いやすさです。

システムコールを行ったり、メモリを割り当てたりする必要はありません。複雑なことは何もありません。シェルでは、単一の文字を使用します:|。これにより、特定のタスクにシンプルな(または複雑な)ツールを組み合わせることで並外れた力が得られます。

テキストをきちんと並べ替えるなど、一般的な日常的な作業をいくつか行います。たくさんの名前をリストするコマンドがあるかもしれません。 (私の例では、listofrandomnames.comの厚意により、一連の名前を含むファイルを使用します。)パイプを使用すると、次のようなことができます。

$ cat names.txt
Sally Weikel
Dana Penaflor
Christine Hook
Shaneka Flythe
Almeda Crook
Freddie Lindley
Hester Kersh
Wanda Ruse
Megan Mauzy
Samuel Mancha
Paris Phipps
Annika Accardo
Elena Nabors
Caroline Foti
Jude Nesby
Chase Gordy
Carmela Driggers
Marlin Ostendorf
Harrison Dauber
$ cat names.txt | awk '{print $2 ", " $1}' | sort | uniq | column -c 100
Accardo, Annika     Hook, Christine     Ostendorf, Marlin
Crook, Almeda       Kersh, Hester       Penaflor, Dana
Dauber, Harrison    Lindley, Freddie    Phipps, Paris
Driggers, Carmela   Mancha, Samuel      Ruse, Wanda
Flythe, Shaneka     Mauzy, Megan        Weikel, Sally
Foti, Caroline      Nabors, Elena
Gordy, Chase        Nesby, Jude

これはほんの一例です。数千があります。パイプを使用することで著しく簡単になる他のいくつかの特定のタスクについては、 このページ のセクション「The Unix Philosophy」を参照してください。


この回答を強調するには、プレゼンテーション「 」のスライド4から9を参照してください。「Zshがシェルよりも優れている理由」


上記のコマンドには [〜#〜] uuoc [〜#〜] が含まれています。これは、テキストを生成する任意のコマンドのプレースホルダーであるため、そのままにしておきます。

14
Wildcard

そこで、PDP-10/TOPS-10のマニュアルを探して、パイプの前の状態を把握することで、これについて少し調べてみました。私は this を見つけましたが、TOPS-10はグーグルするのが非常に難しいです。パイプの発明に関するいくつかの優れた参考文献があります: McIlroyへのインタビューNIXの歴史と影響について

これを歴史的な文脈に入れなければなりません。私たちが当たり前と思っている現代的なツールや便利さはほとんどありませんでした。

「当初、トンプソンはPDP自体をプログラミングすることすらせず、代わりにGE-635マシンでGEMAPアセンブラーのマクロセットを使用していました。」(29)紙テープがGE 635で生成され、次にテストされましたリッチー氏によれば、PDP-7までは「原始的なUnixカーネル、エディター、アセンブラー、単純なシェル(コマンドインタープリター)、およびいくつかのユーティリティ(Unix rm、cat、cpコマンドなど)が完成していました。つまり、オペレーティングシステムは自己サポート型であり、プログラムは紙テープに頼ることなく作成およびテストでき、PDP-7自体で開発が継続されました。」

PDP-7は次のようになります 。対話型ディスプレイまたはハードディスクがないことに注意してください。 「ファイルシステム」は磁気テープに保存されます。プログラムとデータ用に最大64kBのメモリがありました。

その環境では、プログラマーはハードウェアを直接アドレス指定する傾向があり、コマンドを発行してテープをスピンアップし、一度に1つずつテープインターフェイスから直接読み取って文字を処理します。 UNIXはこれに関する抽象化を提供したため、「テレタイプからの読み取り」と「テープからの読み取り」が別々のインターフェースであるのではなく、それらが1つに結合され、「一時的なコピーをディスクに保存せずに他のプログラムの出力から読み取り」という重要なパイプが追加されました。またはテープ」。

これがgrepの発明に関するMcIlroyです。これは、UNIX以前の環境で必要な作業量を合計するのに適していると思います。

「Grepは私のために発明されました。私は音声合成装置を介してテキストを読み上げるプログラムを作成していました。音声規則を発明したので、失敗する可能性のある単語がないかWebsterの辞書をチェックします。たとえば、ダイグラフにどのように対処しますか ' ui」、「フルーツ」、「ギル」、「ギルティ」、「アングイッシュ」、「イントゥイット」、「ベギン」など、さまざまな方法で発音されますか?辞書をedの限られたバッファーに収まるように分割して使用しますリストを選択するためのグローバルコマンドです。提案された各ルールがどのように機能するかを確認するために、edを繰り返しスキャンして、このリストを削っていきます。」

「ディクショナリを分割する必要があったため、このプロセスは退屈で非常に無駄でした(分割コピーをオンラインに残す余裕がありませんでした。次に、各部分を/ tmpにコピーし、2回スキャンしてgコマンドを実行しました。そして、ついにそれを捨てましたが、これにも時間がかかりました。」

「ある午後、私はケントンプソンに、正規表現認識機能をエディターから引き上げて、それを実行するためのワンパスプログラムを作成できるかどうか尋ねました。彼はそう言った。翌朝、grepという名前のプログラムを発表するメールにメモがあった。それは魅力のように機能しました。そのおかしな名前が何を意味するのかを尋ねられたとき、ケンはそれが明白であると言いました。

その最初の部分をcat names.txt | awk '{print $2 ", " $1}' | sort | uniq | column -c 100の例と比較してください。オプションが「コマンドラインのビルド」であるか「アセンブラーで手動で目的のためにプログラムを作成する」かである場合は、コマンドラインをビルドする価値があります。 (紙の)マニュアルを読むのに数時間かかるとしても。その後、将来の参照のためにそれを書き留めることができます。

5
pjc50

Pipesの天才は、3つの重要なアイデアを組み合わせていることです。

まず、パイプは「コルーチン」の実用的な実装であり、1958年にコンウェイによって造られた用語であり、有望でしたが、パイプの前にはほとんど実用化されていませんでした。

次に、シェル言語でパイプを実装することにより、トンプソンらは最初の本当の「接着剤言語」を発明しました。

これらの2つのポイントにより、再利用可能なソフトウェアコンポーネントを低レベルの最適化された言語で効率的に開発し、接着して、より大規模で複雑な機能を形成できます。彼らはこれを「大規模プログラミング」と呼んだ。

第3に、ファイルアクセスに使用されたのと同じシステムコールを使用してパイプを実装すると、プログラムをユニバーサルインターフェイスで作成できます。これにより、ソフトウェアの問題に対する真に普遍的な解決策が可能になり、ソフトウェアコンポーネントに単一の変更を加えることなく、インタラクティブに、ファイルのデータを使用して、より大きなソフトウェアシステムの一部として使用できます。コンパイルや設定は必要ありません。いくつかの単純なシェルコマンドを使用するだけです。

学習曲線をたどるのが気になるなら、UNIXソフトウェアは、40年前と同じくらい今日でも便利です。私たちは常に彼らがすでに知っていて解決策を構築したものを常に再発明しています。そして重要な進歩は単純なパイプでした。その後の唯一の真の革新は、80年代のインターネットの構築でした。劇的に、UNIXは別のAPIを作成することにより、その実装を失敗させました。私たちはまだ結果に苦しんでいます...ああ、そうです、80年代後半に人気となったビデオディスプレイとマウスに何かがありました。しかし、それはWIMPの場合です。

1
EvertW