dd を使用して任意のデータを生成し、「部分読み取り警告」が発生します。今警告後のデータは本当にランダムですか?

dd を使用して任意のデータを生成し、「部分読み取り警告」が発生します。今警告後のデータは本当にランダムですか?

任意のデータを含む1TBファイルを作成しましたdd if=/dev/urandom of=file bs=1M count=1000000。ここで進捗状況を確認し、kill -SIGUSR1 <PID>次のようになります。

691581+0 Datensätze ein
691580+0 Datensätze aus
725174190080 Bytes (725 GB) kopiert, 86256,9 s, 8,4 MB/s
800950+1 Datensätze ein
800950+0 Datensätze aus
839856947200 Bytes (840 GB) kopiert, 99429,5 s, 8,4 MB/s
dd: warning: partial read (809620 bytes); suggest iflag=fullblock
803432+1 Datensätze ein
803431+1 Datensätze aus
842459273876 Bytes (842 GB) kopiert, 99791,3 s, 8,4 MB/s

警告を説明できません。それは何を言うか。警告の後、私のファイルは本当にランダムですか、それとも何か問題がありますか?800950+1 Datensätze ein+0または+1はどういう800950+0 Datensätze aus意味ですか?警告後+1。エラー回数ですか?

ベストアンサー1

要約:dd正しく使用するのが難しい奇妙なツールです。これについて説明する多くのチュートリアルがありますが、使用しないでください。dd「Unix Streetの信任」の雰囲気があります。しかし、自分がしていることを本当に理解しているなら、10フィートの柱に触れてはいけないことがわかります。

dd各ブロックはシステムコールread(値として定義されているbs)を一度呼び出します。readシステムコールが指定されたバッファサイズと同じデータを返す保証はありません。これは通常、通常のファイルおよびブロックデバイスでは機能しますが、パイプや一部の文字デバイスでは機能しません。バラよりddはいつデータのコピーに適していますか? (またはread()とwrite()が部分的な場合)より多くの情報を知りたいです。readシステムコールがデータブロック全体より少ないデータを返す場合、dd部分ブロックが送信されます。それでも指定された数のブロックがコピーされるため、送信される合計バイト数は要求されたバイト数より少なくなります。

「部分読み取り」に関する警告は、正確に次のように通知されます。読取りの1つが部分読取りであるため、dd不完全なブロックが送信されました。ブロック数は、+1ブロックが部分的に読み込まれたことを意味します。出力数があるため、+0すべてのブロックが読み取りとして書き込まれます。

これはデータのランダム性には影響しません。dd書き込まれたすべてのバイトはから読み込まれたバイトです/dev/urandom。しかし、予想より少ないバイトを取得します。

Linuxは/dev/urandom任意に大規模な要求を処理できます(ソース:extract_entropy_userdrivers/char/random.cなので、dd通常読んでも安全です。ただし、大量のデータを読み取るには時間がかかります。プロセスがシグナルを受信すると、read出力バッファを満たす前にシステムコールが返されます。これは通常の動作であり、readループ内でアプリケーションによって呼び出される必要があります。dd歴史的な理由からそうしません(ddその起源はあいまいですが、特別な要件があり、決して適応されていないテープにアクセスするツールで始まったようです)。一般的なツール)。進捗状況を確認すると、dd読み取りを中断するプロセスに信号が送信されます。コピーされたバイト数の合計を確認するかdd(中断しないでください。進行状況の確認や一時停止なし)、ddこれまでにコピーされたバイト数がわかります。この場合、バイト数は不明です。バイトが残っています。コピーするバイトです。

バージョンddGNU coreutilsからfullblock(非埋め込み Linux と Cygwin で見つかりました) にはループから呼び出すフラグがあるのでdd(for と同じ) チャンク全体が常に送信されます。エラーメッセージはそれを使用するように助言します。非常に特殊な状況(主にテープにアクセスするとき)を除いて、常に入出力フラグに使用する必要があります。これを使用している場合は、通常、より良い解決策があります(参照)。以下)。readwritedd

dd if=/dev/urandom iflag=fullblock of=file bs=1M count=1000000

dd実行するアクションを決定する別の方法は、チャンクサイズが1のチャンクを渡すことです。その後、ブロック数からコピーされたバイト数がわかります。ただし、最初のブロックを読み取る前にaが中断された場合、何が起こるのかわかりませんread(実際には可能性は低いかもしれませんが)。しかし、動作しても非常に遅いです。

一般的な使用推奨事項ddは次のとおりです。使用しないでくださいdd。多くの場合、デバイスにアクセスするための低レベルのコマンドとして宣伝されますが、dd実際にはそうではありません。すべての魔法はデバイスファイル(/dev/…)セクションで発生し、dd簡単に誤用される可能性がある一般的なツールであるため、データが失われます。ほとんどの場合、少なくともLinuxでは、必要なものを達成するより簡単で安全な方法があります。

たとえば、ファイルの先頭から特定のバイト数を読み取るには、次のように呼び出しますhead

head -c 1000000m </dev/urandom >file

私のコンピュータで迅速なベンチマークを行いましたが、ddチャンクサイズとhead

最初にいくつかのバイトをスキップする必要がある場合は、tail入力をパイプしますhead

dd if=input of=output count=C bs=B seek=S
<input tail -c +$((S*B+1)) | head -c $((C*B)) >output

進行状況を確認するには、lsofファイル表示オフセットを呼び出します。これは、文字デバイスではなく通常のファイル(例の出力ファイル)でのみ機能します。

lsof -a -p 1234 -d 1
cat /proc/1234/fdinfo/1

電話してもいいpv進捗レポートを受け取ります(より良いdd)。ただし、パイプラインの追加項目が必要です(パフォーマンスの面ではほとんど目立たない)。

おすすめ記事