追加読書

追加読書

ブライアン・カーニガンが説明します。この動画初期のBell Labsが小さな言語/プログラムに魅力を感じたのは、メモリの制約によるものです。

大きなマシンは64キロバイト(MやGではなくK)を持っているため、個々のプログラムは非常に大きくできないため、小さなプログラムを書くのは自然な傾向があり、基本的には入力出力であるパイプメカニズムがあります。リダイレクトを使用すると、あるプログラムを別のプログラムにリンクできます。

ただし、プログラム間で転送するには、データをRAMに保存する必要があることを考慮すると、これがメモリ使用量を制限する方法はわかりません。

~からウィキペディア:

ほとんどのUnixシリーズシステムではパイプラインのすべてのプロセスが同時に開始されます。、対応するストリームは、適切に接続され、マシン上で実行される他のすべてのプロセスとともにスケジューラによって管理されます。 Unixパイプを他のパイプ実装と区別する重要な側面は、バッファリングの概念です。たとえば、送信者は毎秒5000バイトを生成できますが、受信者はデータを失うことなく1秒あたり100バイトしか許可できません。代わりに、送信プログラムの出力がバッファに格納されます。受信プログラムがデータを読み取る準備が整うと、パイプラインの次のプログラムはバッファからデータを読み取ります。 Linuxでは、バッファサイズは65536バイト(64KB)です。必要に応じて、bfrというオープンソースのサードパーティ製フィルタを使用してより大きなバッファを提供できます。

これはアプレットの目的を完全に崩壊させるので、私をさらに混乱させます(たとえ特定の規模でモジュール化されても)。

最初の問題(メモリ制限がデータサイズに依存する問題)を解決するために私が考えることができる唯一の方法は、大規模なデータセットが当時まったく計算されず、実際の問題はパイプラインです。 。しかし、Wikipediaの引用に太字で表示されている内容を見ると、これさえ私を混乱させます。なぜなら、プログラムは一度に1つずつ実装されていないからです。

これはすべて一時ファイルを使用する場合は意味がありますが、パイプは(スワップを使用しない限り)ディスクに書き込まないことです。

例:

sed 'simplesubstitution' file | sort | uniq > file2

sedファイルを1行ずつ読み、吐き出すことは明らかです。ただし、sortリンクされたビデオではBKが述べたようにピリオドなので、すべてのデータをメモリに読み込む必要があります(それともそうですか?)。それからに渡す必要があります。uniq(私の考えには)一度に1行になります。プログラム。ただし、最初のパイプと2番目のパイプの間には、すべてのデータがメモリに存在する必要があります。そうですか?

答え1

データをRAMに保存する必要はありません。読者がそこにいないかフォローできない場合、パイプはライターをブロックします。 Linux(そして私が考えている他のほとんどの実装)には少しバッファリングがありますが、必要ではありません。言ったように追跡装置そしてジェイドBP(望むより後者の答え)、Unixの初期バージョンはディスクへのパイプをバッファリングし、これがメモリ使用量を制限するのに役立つ方法です。処理パイプは小さなプログラムに分割することができ、各プログラムはディスクバッファの制限内でいくつかのデータを処理します。小さなプログラムはメモリを少なくし、パイプを使用すると、処理がシリアル化される可能性があることを意味します。最初のプログラムが実行され、出力バッファを埋め、一時停止され、次に2番目のプログラムがスケジュールされ、バッファを処理するなどの操作を実行します。最新のシステムは初期のUnixシステムよりもはるかに大きく、複数のパイプラインを並列に実行できますが、大量のデータに対しても同様の効果を見ることができます(この技術のバリエーションは「ビッグデータ」処理に使用されます)。

あなたの例では

sed 'simplesubstitution' file | sort | uniq > file2

sedデータは必要に応じて読み取られ、読み取る準備が整うとすぐに書き込まれfileますsortsort準備ができていない場合、書き込みはブロックされます。データはメモリに保存されますが、これは具体的でsortあり、sortすべての問題を処理する準備ができています(ソートするデータ量が多すぎる場合は一時ファイルを使用します)。

以下を実行して、ブロックの動作を確認できます。

strace seq 1000000 -1 1 | (sleep 120; sort -n)

これは大量のデータを生成し、読み取る準備ができていないプロセスに転送します。何もない最初の2分。多くのwrite作業が進行中であることがわかりますが、seqまもなく停止してカーネルによってブロックされ、2分が経過するのを待ちます(システムコールを待つwrite)。

答え2

ただし、プログラム間で転送するには、データをRAMに保存する必要があることを考慮すると、これがメモリ使用量を制限する方法はわかりません。

これはあなたの根本的な間違いです。以前のバージョンのUnixは、パイプデータをRAMに保存しませんでした。ディスクに保存します。パイプには、次のように表示される光ディスクデバイスのiノードがあります。配管設備。システム管理者は、/etc/configどのディスク上のどのボリュームがパイプデバイスであり、どのボリュームがパイプデバイスであるかを指定するために呼び出されるプログラムを実行します。ルートデバイスの中ダンプ装置

処理するデータの量は、次の事実によって制限されます。直接ブロックディスクのiノードは保存に使用されます。このメカニズムは、パイプからデータを読み取るために使用されるアルゴリズムが通常のファイルを読み取るために使用されるアルゴリズムとほぼ同じであるため、コードをより簡単にします。パイプは検索できず、バッファは循環であるという事実によっていくつかの調整が行われました。

このメカニズムは1980年代半ばに他のメカニズムに置き換えられました。 SCO XENIXは、iノードをコアバッファに置き換える「高性能パイプライン」を確保しました。 4BSDは名前のないパイプをソケットペアにします。 AT&TはSTREAMSメカニズムを使用してパイプを再実装しました。

もちろん、sortプログラムは32KiB入力ブロック(または32KiBが利用できない場合に割り当てることができるより少ない量のメモリ)に対して限られた内部ソートを実行し、ソート結果を中間ファイルに書き込み、外部マージソートを実行しstmX??ます/usr/tmp/。最終結果を提供するために中間ファイルにあります。出力。

追加読書

  • スティーブD.フェイト(1996)。 「プロセス間通信」。UNIX内部:実用的なアプローチ。アディソン - ウェスリー。 ISBN 9780201877212.
  • バッハ、モリスJ.(1987)。 「ファイルシステムシステムコール」。 Unixオペレーティングシステムの設計。フレンティスホール。 ISBN 0132017571.
  • スティーブンV.エアハート(1986)。 「config(1M)」。 Unixプログラマーズマニュアル:3.システム管理機能。ホルト、ラインハルト、ウィンストン。 ISBN 0030093139。23〜28ページ。
  • アビジットメノンセン(2020-03-23)。Unixパイプはどのように実装されていますか?。 toroid.org.

答え3

あなたは部分的に正しいですが偶然

あなたの例では、すべてのデータは実際にパイプ「間」から読み取る必要がありますが、メモリ(仮想メモリを含む)に常駐する必要はありません。一般的な実装では、一時sortファイルを部分的にソートしてマージして、RAMに収まらないデータセットをソートできます。ただし、各要素を読み取る前にソートされたシーケンスを出力できないというのは、与えられた事実です。これは明らかです。はい。sort2番目のパイプへの出力は、1番目のパイプのすべての内容を読み取った後にのみ開始できます(そしてすべての操作を完了し、一時ファイルを部分的にソートすることもできます)。しかしそれはいいえすべてRAMに保存する必要があります。

しかし、これはパイプの動作方法とは何の関係もありません。パイプには名前を付けることができます(伝統的に名前が付けられています)。これは、ファイルと同様に、ファイルシステムに場所があることを意味します。これはパイプライン、つまりファイルでした(最適化が可能な物理メモリの可用性に応じて書き込みがマージされました)。

今日のパイプは、データがコピーされる小さな、有限のサイズのカーネルバッファです。概念的に発生する。カーネルが役に立つ場合は、仮想マシンのトリックを使用してコピーを削除できます(たとえば、ファイルからパイピングすると通常は別のプロセスで同じページを読み取ることができるため、2つのコピーではなく1回の読み取り操作で終わります)場合によっては、バッファキャッシュがすでに使用しているよりも多くのメモリが必要になる場合があります。

パイプラインが小さく、サイズが制限されている場合は、不明な(おそらく大きな)量のデータにどのように適用しますか?簡単です。もしスペースがなくなったら、スペースが再現されるまでブロックを書き込みます。

記憶力が非常に不足したときに多くの簡単なプログラムの原理が非常に役に立った時がありました。なぜなら、一度に1つずつ、段階的に作業を実行できるからです。最近では、若干の柔軟性を除いて、長所はもはや大きくないと言います。
しかし、パイプラインは非常に効率的に実装されている(そうする必要があります!)、欠点がなく、うまく機能し、人々に慣れることが確立されているので、パラダイムを変更する必要はありません。

関連情報