web-dev-qa-db-ja.com

ddは1 GBの代わりに32 MBのランダムファイルを作成しています

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

なにが問題ですか?

編集:

このトピックの素晴らしい回答のおかげで、32チャンクを32 MBの大きさにして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
49
Trismegistos

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

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

通常のファイルはほぼどんなバッファサイズでも(そのバッファがRAMに収まる限り)読むことができますが、デバイスと「仮想」ファイルはしばしば個々の呼び出しに非常に近く働き、それらが生成するデータ量に関して任意の制限がありますread()を呼び出します。

/dev/urandomの場合、この制限は drivers/char/random.curandom_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は要求されたよりも少ないデータを受け取った後に再試行しません - あなたは32 MiBを得ます、それだけです。 (Kamilの答えのように自動的に再試行させるには、iflag=fullblockを指定する必要があります。)


また、「単一のread()のサイズ」とは、バッファ全体が一度にメモリに収まる必要があることを意味します。したがって、ブロックサイズが大きいと、ddによるメモリ使用量も増えます。

16〜32 MiBブロックを超えても通常はパフォーマンスが向上しないため、これはまったく意味がありません。システムコールはここでは遅い部分ではなく、乱数ジェネレータです。

簡単にするために、単にhead -c 1G /dev/urandom > outputを使用してください。

93
grawity

iflag=fullblockが指定されていない限り、ddibsより少ない値で読み取ることができます(注:bsibsobsの両方を指定します)。 0+1 records inは、0フルブロックおよび1部分ブロックが読み取られたことを示します。ただし、フルブロックまたはパーシャルブロックではカウンタが増えます。

この場合、dd1Gより小さいブロックを読み取る正確なメカニズムはわかりません。ブロックは書き込まれる前にメモリに読み込まれると思いますので、メモリ管理が妨げる可能性があります(ただしこれは推測にすぎません)。 編集: この同時回答 は、この特定のケースでdd1Gより小さいブロックを読み取るメカニズムを説明しています。

とにかく、私はそのような大きな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
21