次のコンテンツをクロールするとしましょう。とても大きいファイルですが、一度に複数の部分を見たいです。次のことを行うとしましょう。
$ cat /dev/sda1 | less
JavaやActionScriptなどの言語を使用するプログラマーとして、このコードを見ると、Bashが最初にコマンドを実行する様子を想像していますcat /dev/sda1
。すべてコマンドをRAMに保存してから、表示されるless
非常に大きな「ダミー変数」にアクセスできるコマンドを実行します-
。
これがBashが何をするのか(つまり、特に悪いファイルがシステムのRAM容量より大きい場合は、別のコマンドを使用する必要があると思いますか?または、大容量データに合わせてパイプラインを最適化する方法はありますか?
答え1
いいえ、すべてをメモリにロードするわけではなく、設計には非現実的な方法です。バッファを使用してパイプの左側の出力をバッファリングし、これらのバッファをパイプの右側のコマンド入力に接続します。
マニュアルページには、man 7 pipe
次のタイトルのその他のU&L Q&Aだけでなく、すべての詳細が含まれています。パイプバッファはどれくらい大きいですか?
答え2
読み取りはデータが利用可能になるまでブロックされ、書き込みはパイプがいっぱいになるとブロックまたは失敗します。パラメータがほとんどありません。パイプバッファ、パイプサイズそしてO_非遮断パイプラインで重要な役割を果たします。
PIPE_BUF の値は 'ulimit -a' で決定できます。これは limits.h で定義されています。 PIPE_BUFは保証されたサイズを制御します。原子書き込み。これは安全なマルチスレッドアプリケーションを作成するのに役立ちます。
PIPE_SIZE はページサイズによって異なります。 2.4カーネルではページサイズ(4KB)に対応します。ただし、2.6以降のバージョンは16ページ(64KB)配列にマップされます。これは、パイプライン_fs_i.hファイルでPIPE_BUFFERS(16)として定義されます。最新のカーネルには、ページサイズを増やすことができるfcntlとF_SETPIPE_SZがあります。
O_NONBLOCK は部分書き込みと遅延書き込みを許可します。ただし、O_NONBLOCK が有効になっているがパイプに書き込むバイト数が PIPE_BUF より大きい場合、パイプがいっぱいになると書き込みは失敗し、そうでない場合は戻り値によって他のプロセスのデータと混在します。書き込み値がずれています。
答え3
オプションを試してください-B
。 64kバッファのみが使用されます。
cat /dev/sda1 | less -B
からman less
:
-B または --auto-buffers デフォルトでは、バッファはパイプからデータを読み取るときに必要に応じて自動的に割り当てられます。パイプから大量のデータを読み取ると、大量のメモリが割り当てられる可能性があります。 -Bオプションはパイプバッファの自動割り当てを無効にするため、パイプは64K(または-bオプションで指定されたスペースの量)のみを使用します。警告:-Bを使用すると、ファイルの最後に見た部分だけがメモリに保存され、古いデータが失われるため、表示エラーが発生する可能性があります。