Bashで大量のデータをパイプする方法は?

Bashで大量のデータをパイプする方法は?

次のコンテンツをクロールするとしましょう。とても大きいファイルですが、一度に複数の部分を見たいです。次のことを行うとしましょう。

$ 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を使用すると、ファイルの最後に見た部分だけがメモリに保存され、古いデータが失われるため、表示エラーが発生する可能性があります。

関連情報