ハードウェアリソースを無駄にせずに動的ストリーム圧縮を行いますか?

ハードウェアリソースを無駄にせずに動的ストリーム圧縮を行いますか?

200GBの空きディスク容量、16GBのRAM(デスクトップとカーネルが約1GBを占める)、6GBのスワップ領域があります。

240GBの外付けSSDがあり、そのうち70GBを使用し、残りは無料なので、ディスクにバックアップする必要があります。

通常、dd if=/dev/sdb of=Desktop/disk.img最初にディスクを作成してから圧縮しますが、最初にイメージを作成することはオプションではありません。これは、圧縮段階で空き容量が圧縮され、最終イメージが圧縮されても必要以上のディスク容量が必要になるためです。アーカイブは私のディスクに簡単に入れることができます。

ddデフォルトでは、STDOUTに書き込んでgzipSTDINから読み取ることができるので、理論的には書き込むことができますが、バイトをdd if=/dev/sdb | gzip -9 -生成するよりも読み込むgzipのにはるかに時間がかかります。dd

~からman pipe:

パイプの書き込みの終わりに書き込まれたデータは、パイプの読み取りの最後から読み取られるまでカーネルによってバッファリングされます。

私は|パイプラインを実際のパイプラインとして想像しています。あるアプリケーションはデータをパイプラインキューにプッシュし、他のアプリケーションはできるだけ早くパイプラインキューからデータを取得します。

パイプの反対側で処理できるデータよりも左側のプログラムがより速くデータを書き込むとどうなりますか?過度のメモリやスワップ領域の使用は発生しますか?または、カーネルはディスクにFIFOを作成してディスクを埋めようとしますか?それともSIGPIPE Broken pipeバッファが大きすぎると失敗しますか?

デフォルトでは、これは2つの質問に帰結します。

  1. 一度に読み取ることができるよりも多くのデータがパイプにプッシュされると、どのような影響と結果が発生しますか?
  2. 圧縮されていないデータストリーム全体をディスクに保存せずにデータストリームをディスクに圧縮する安定した方法は何ですか?

注 1: 断片化やその他の要因によってコンテンツ全体が破損しないようにするため、最初に使用した 70 GB の正確なコピーを作成して動作するシステムやファイルシステムを取得することは期待できません。

答え1

ddデータブロックは一度に1つずつ読み書きし、未解決のデータブロックは1つだけです。だから

valgrind dd if=/dev/zero status=progress of=/dev/null bs=1M

dd1MBのメモリが使用されます。チャンクのサイズを変更して削除すると、valgrind速度に与える影響を確認できます。dd

gzip入力するときはdd一致速度を遅くしてくださいgzip。メモリ使用量が増えず、カーネルがディスクにバッファを保存することもできません(カーネルはこれを行う方法がわかりません)。渡す交換)。チューブ破裂signal(7)は、チューブの一端が死んだときにのみ発生しますwrite(2)

だから

dd if=... iconv=fullblock bs=1M | gzip -9 > ...

欲しいものを達成する安全な方法です。

パイピング中に読み取りプロセスが維持されない場合、最終的に書き込みプロセスはカーネルによってブロックされます。これを実行すると見ることができます

strace dd if=/dev/zero bs=1M | (sleep 60; cat > /dev/null)

1MBの読み取りが表示されddたら、aを実行しwrite()、実行中にしばらく待ちますsleep。これがパイプの両側がバランスをとる方法です。書き込みプロセスが速すぎる場合、カーネルは書き込みをブロックし、読み取りプロセスが速すぎるとカーネルは読み取りをブロックします。

答え2

技術的には、以下は必要ありませんdd

gzip < /dev/drive > drive.img.gz

これを使用する場合は、dd常にデフォルトより大きいブロックサイズを使用する必要がありますdd bs=1M。それ以外の場合は、システムコールの地獄に苦しんでいます(デフォルトのddブロックサイズは512バイトで、そのread()sとwrite()sは4096システムコールごとにあるため、MiBオーバーヘッドが大きすぎます)。途方もない)。

gzip -9より多くのCPUが使用されますが、表示する内容はほとんどありません。遅い場合は、gzip圧縮レベルを下げるか、別の(高速)圧縮方法を使用してください。

イメージではなくファイルベースのバックアップを実行している場合は、圧縮するかどうかを決定するいくつddかのロジックがあります(さまざまなファイル形式に対してこれを行うことは意味がありません)。dartaralternative`)はこれを行うオプションの例です。

空き領域がゼロの場合(TRIM後に安定してゼロを返すSSDであり、キャッシュをfstrim実行および削除するため)、ddwithconv=sparseフラグを使用して圧縮されていないループマウント可能なスパースイメージを作成することもできます。このイメージはゼロのディスク領域を使用します。ゼロ地域の場合。スパースファイルをサポートするファイルシステムでイメージファイルをサポートする必要があります。

または、一部のファイルシステムでは、使用されている領域のみをイメージできるプログラムがあります。

答え3

パフォーマンスに加えて、悪影響はありません。パイプには通常64Kのバッファがあり、それ以降はgzipより多くのデータを読み込むまでパイプへの書き込みがブロックされます。

答え4

たぶんファイルが必要で、tarを使うこともできます。誰かがすでに要求したように、目的のコンテンツが含まれていないブロックをゼロで埋めることができます。ゼロとして未使用のスペースを消去する(ext3、ext4)

それからpigz一般的にgzip

関連情報