ddは1 GBではなく32 MBのランダムファイルを生成しています


50

1 GBのランダムファイルを作成したいので、次のコマンドを使用しました。

dd if=/dev/urandom of=output bs=1G count=1

しかし、代わりにこのコマンドを起動するたびに32 MBのファイルを取得します。

<11:58:40>$ dd if=/dev/urandom of=output bs=1G count=1
0+1 records in
0+1 records out
33554431 bytes (34 MB, 32 MiB) copied, 0,288321 s, 116 MB/s

なにが問題ですか?

編集:

このトピックのすばらしい回答のおかげで、32GBの32MBのチャンクを読み取り、1GBにするソリューションがありました:

dd if=/dev/urandom of=output bs=32M count=32

1 GBを直接メモリに読み取り、その後ディスクに書き込む別のソリューションが提供されました。このソリューションは多くのメモリを消費するため、優先されません。

dd if=/dev/urandom of=output bs=1G count=1 iflag=fullblock

3
私見私はまったく多くの有効なユースケースがあるとは思わないdd。私はheadcatまたはrsyncほとんど常にその場所で使用します。また、代替案が通常より安全である理由の1つであるかどうかについての質問。
バクリウ

@Bakuriu-また、ゼロでいっぱいのファイルを作成したい場合(または、その中に何があるか気にしない場合)、truncateを使用します。はるかに高速です。
コンラッドガジェウスキ

@KonradGajewski FYI truncateは、スパースファイルを作成しようとします(問題がある場合)
Xen2050

5
@Bakuriu head、POSIXにない-cオプションなしではこのタスクを実行できません。これを解決できるバージョンは知りません。完全に非標準のユーティリティです。それもそこにもありません。マニュアルページをざっと見ても、この問題をどのように解決できるかわかりません。catrsync
カズ

技術的には、/dev/urandomどちらか... POSIXではありません
grawity

回答:


92

bs、バッファサイズは、ddによって実行される単一のread()呼び出しのサイズを意味します。

(たとえば、両方bs=1M count=1bs=1k count=1kは1 MiBファイルになりますが、最初のバージョンでは1ステップで実行され、2番目のバージョンでは1024個の小さなチャンクで実行されます。)

通常のファイルは、ほぼすべてのバッファーサイズで読み取ることができます(そのバッファーがRAMに収まる限り)が、デバイスおよび「仮想」ファイルは、個々の呼び出しに非常に近い動作をすることが多く、生成されるデータ量に任意の制限がありますread()呼び出し。

の場合/dev/urandom、この制限はdrivers / char / random.cのurandom_read()で定義されています

#define ENTROPY_SHIFT 3

static ssize_t
urandom_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
{
    nbytes = min_t(size_t, nbytes, INT_MAX >> (ENTROPY_SHIFT + 3));
    ...
}

これは、関数が呼び出されるたびに、要求されたサイズを33554431バイトにクランプすることを意味します。

デフォルトでは、他のほとんどのツールとは異なり、ddは要求されたよりも少ないデータを受信した後は再試行しません。32MiBを取得しました。(Kamilの答えのように、自動的に再試行させるには、を指定する必要がありますiflag=fullblock。)


また、「単一のread()のサイズ」は、バッファ全体が一度にメモリに収まらなければならないことを意味するため、大量のブロックサイズはddによる大量のメモリ使用量にも対応することに注意してください。

そして、それは無意味です。なぜなら、通常、16〜32 MiBブロックを超えるとパフォーマンスが得られないからです。syscallはここでは遅い部分ではなく、乱数ジェネレーターがそうです。

したがって、単純にするために、を使用しますhead -c 1G /dev/urandom > output


7
「...あなたは〜16-32のMIBブロックの上に行くとき、通常は任意のパフォーマンスを得られないだろう」 -あなたは多く獲得していない傾向があり、私の経験では、または64から128以上さえも失うパフォーマンスキロバイト。その時点で、あなたはシステムコールのコストに対するリターンの減少に満足しており、キャッシュの競合が役割を果たし始めています。
marcelm

3
@marcelmブロックサイズが1〜2 MB、場合によっては最大8 MB程度になるとIOパフォーマンスが向上する高性能システムの設計を支援しました。LUNごと。また、ファイルシステムは複数の並列LUNを使用して構築されたため、最高のパフォーマンスを得るためには、IOに複数のスレッドを使用し、それぞれが1 MB以上のブロックを実行する必要がありました。持続IOレートは1 GB /秒を超えていました。そして、それらはすべて回転ディスクであったため、ブロックサイズが16 MBまたは32 MBブロックにまで拡大するにつれて、SSDの高性能アレイがより速くデータを飲み込んだり生成したりすることがわかります。簡単に。さらに大きいかもしれません。
アンドリューヘンレ

4
これはPOSIX ユーティリティのiflag=fullblock GNU拡張機能であることに明示的に注意します。質問はLinuxを指定していないので、Linux以外のシステムで同様の問題を解決しようとする将来の読者が混乱しないように、Linux固有の拡張機能の使用はおそらく明示的に注意する必要があると思います。dd
アンドリューヘンレ

6
@AndrewHenleああ、面白い!私はdd自分のマシンで1kから512Mのブロックサイズで簡単なテストを行いました。Intel 750 SSDから読み取ると、2MiBブロックで最適なパフォーマンス(約1300MiB / s)が達成され、結果とほぼ一致しました。ブロックサイズを大きくしても、助けにも妨げにもなりません。から読み取ると/dev/zero、最適なパフォーマンス(ほぼ20GiB / s)は64KiBおよび128KiBブロックでした。小さいブロック大きいブロックの両方でパフォーマンスが低下し、以前のコメントとほぼ一致しました。結論:実際の状況のベンチマーク。そしてもちろん、私たちはどちらもベンチマークしていません/dev/random:P
marcelm

3
@ Xen2050私はさらにいくつかの簡単なテストを行いましたが、ddより速いようです。head8KiBの読み取りと2つの4KiBの書き込みを使用する簡単なトレースは、興味深いことです(Debian 9.6 / Linux 4.8のGNU coreutils 8.26)。head速度は確かにdd bs=4kとの間のどこかにありdd bs=8kます。head速度はに比べて〜40%dd if=/dev/zero bs=64k低下し、に比べて〜25%低下していdd if=/dev/nvme0n1 bs=2Mます。/dev/zeroもちろん、読み取りからのCPU制限は大きくなりますが、SSDのI / Oキューイングも役割を果たします。予想以上に大きな違いです。
marcelm

21

dd未満読むことができるibs:(注bs両方を指定ibsしてobsいない限り、)iflag=fullblock指定されています。完全なブロックと部分的なブロックが読み取ら0+1 records inれたことを示します。ただし、完全または部分的なブロックがあると、カウンターが増えます。01

この特定の場合ddよりも小さいブロックを読み取る正確なメカニズムはわかりません1G。ブロックは、書き込まれる前にメモリに読み込まれるため、メモリ管理が干渉する可能性があります(ただし、これは推測に過ぎません)。編集:この同時回答は、この特定の場合ddよりも少ないブロックを読み取るメカニズムを説明しています1G

とにかく、そんなに大きいのはお勧めしませんbs。を使用しますbs=1M count=1024。最も重要なことはiflag=fullblock 読み取りの試行なしでは読み取りが少なくなる可能性があることですibs(ただしibs=1、これは非常に非効率的です)。

したがって、正確な量のデータを読み取る必要がある場合は、を使用しますiflag=fullblock。注iflagはPOSIXでは必要ddありません。サポートしていない場合があります。この答えに よるとibs=1おそらく正確なバイト数を読み取る唯一のPOSIX方法です。もちろん、変更ibsする場合は、再計算する必要がありますcount。あなたのケースでは下げibs32M以下おそらくさえせずに、問題を解決しますiflag=fullblock

私のKubuntuでは、次のようにコマンドを修正します。

dd if=/dev/urandom of=output bs=1M count=1024 iflag=fullblock
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.