/ dev / randomのddが異なるファイルサイズを与えるのはなぜですか?


26

私はubuntuシステムで次のコマンドを実行しています:

dd if=/dev/random of=rand bs=1K count=2

ただし、実行するたびに、サイズの異なるファイルが作成されます。どうしてこれなの?ランダムデータで満たされた特定のサイズのファイルを生成するにはどうすればよいですか?


1
/dev/random必要な桁数を生成するのに十分なエントロピーがない場合、ブロックします。高品質の疑似ランダム「ランダム性」の量を収集するのに時間がかかるだけです...ランダム性/dev/urandomの低い「ランダム」値を使用するか、エントロピープールを確認します(ループで、必要に応じて待機します)...
Peter.O

この質問も参照してください。
キーストンプソン

3
追加するだけiflag=fullblock
frostschutz

回答:


31

ddの特異な動作とLinuxの特異な動作の組み合わせを観察しています/dev/random。ちなみに、両方が仕事に適したツールになることはめったにありません。

Linux /dev/randomはデータを控えめに返します。これは、疑似乱数ジェネレーターのエントロピーが非常に高速で消滅するという仮定に基づいています。新しいエントロピーの収集は遅いため、/dev/random通常は一度に数バイトしか放棄しません。

dd当初はテープデバイス上で動作することを目的とした、不気味な古いプログラムです。1kBの1ブロックを読み取るように指示すると、1ブロックを読み取ろうとします。読み取りから1024バイト未満が返された場合は、それで十分です。したがってdd if=/dev/random bs=1K count=2、2つのread(2)呼び出しを行います。から読み取るため/dev/random、2つのread呼び出しは通常、使用可能なエントロピーに応じてさまざまな数で、数バイトのみを返します。こちらもご覧くださいデータをコピーするのに適したDDですいつですか?(または、read()およびwrite()が部分的である場合)

OSインストーラーまたはクローンを設計する場合を除き、/dev/randomLinuxでは常に使用しないでください/dev/urandomurandommanページは、やや誤解を招くです。/dev/urandom実際には、寿命の長いキーを生成する場合でも、暗号化に適しています。唯一の制限/dev/urandomは、十分なエントロピーを提供する必要があることです。Linuxディストリビューションは通常、再起動間のエントロピーを保存するため、十分なエントロピーがない可能性があるのは、新規インストール時のみです。エントロピーは、実用的な意味では衰えません。詳細については、「/ dev / urandomからのランドはログインキーに対して安全ですか?」を参照してください。/ dev / randomエントロピープールのフィード?

のほとんどの使用法はddheadまたはなどのツールでより適切に表現されますtail。2kBのランダムバイトが必要な場合は、実行します

head -c 2k </dev/urandom >rand

古いLinuxカーネルを使用すると、

dd if=/dev/urandom of=rand bs=1k count=2

/dev/urandom幸いにも要求されただけのバイトを返したからです。しかし、これはカーネル3.16以降では当てはまらず、現在は32MBに制限されています。

一般に、dd固定数のバイトを抽出するために使用する必要があり、その入力が通常のファイルまたはブロックデバイスから来ていない場合、バイトごとに読み取る必要がありますdd bs=1 count=2048


ddの代わりにheadを使用するためのヒントをありがとう。これにより、必要に応じて/ dev / randomを使用できます。言及したように、おそらく/ dev / urandomで十分ですが、必要に応じて/ dev / randomを使用する方法を知っておくと便利です。
ダニエル

カーネルでは、3.16 /dev/urandom ごとに32mが返されますread()
mikeserv

あるいは、POSIX準拠のコマンドが必要な場合は、ここでトリックを使用できます:unix.stackexchange.com/a/192114 dd if=/dev/urandom ibs=1k obs=1k | dd bs=1k count=2
Rufflewind

11

man 4 randomRHEL 5のボックスに:

読み取られると、/ dev / randomデバイスは、エントロピープール内のノイズの推定ビット数内のランダムバイトのみを返します。

そのマシンで213バイトのサイズのファイルを取得します。男4ランダムに戻る:

/ dev / urandomデバイスは、読み取られると、要求されたバイト数を返します。

のすべての呼び出しから2048バイトを取得します dd if=/dev/urandom of=rand bs=1K count=2

私は、違いは、マシンが呼び出しの間にどれだけのエントロピーを生成するためであると結論付けます dd if=/dev/random ...


ええ、実際には、彼が実際の暗号化アプリケーションでない限り、@ Danielは/ dev / urandomを使用する必要があります。しかしdd if=/dev/random bs=1K count=2、エントロピープールが明らかに流出したときに停止する理由について私は困惑しています。ドキュメントから、エントロピーが増加するまでブロックする必要があるためdd、現在のプールをダンプして終了するのではなく、ファイルをゆっくりと書き出します。
CJC

私もそれについて疑問に思いましたが、それはRHEL、Slackware 13.1、そして最新のArchで一貫しています。RHELはx86_64で、その他は32ビットでした。残念なことに、ddのドキュメントはGNU情報形式であるため、すべてを読んだわけではありません。
ブルースエディガー

Gentooでも一貫しています。
マシューシャーリー

4
@cjc:あなたが呼び出すときからですread(fd, mybuf, 1024)阻止FDに、それはすぐに基本となるデバイスが返すようとして返すいくつかのデータを。読み込む1024バイトがある場合、それを返します。201バイトしかない場合、201を返します。0バイトが使用可能な場合、少なくとも1バイトが使用可能になるまでブロックし、それを返します。
ウォーレンヤング

@WarrenYoungは/ dev / randomからの読み取りで内容を排出しますか?そう思う。
マイケルマルティネス

5

ddデータをドロップするのはなぜですか?... ジルはについては、この魅力的疑問を提起しましたdd
データをコピーするための適切なDDですいつですか?(または、read()およびwrite()が部分的である場合)
その質問からの抜粋を次に示します。

    * ... ddを誤解させるのは難しくありません。たとえば、次のコードを試してください:**
        yes | dd of=out bs=1024k count=10
    、outファイルのサイズを確認します(10MBを大きく下回る可能性が高い)。


(質問の最後の)私のコメントは別として、次のようなものは見ていて面白くて...ファイル内のバイトをキャッチします。 $trnd。私は半任意にbs = 8を選択しました

マウスを動かして、速度が上がるのを見てください。
コンピューターがアイドル状態(AFKおよびネットワークアクティビティなし)で、エントロピープールを使い果たした後、1192バイトのみを収集するのに2 時間 12分かかり、その時点でキャンセルしました。

次に、マウスを連続的に動かして、同じバイト数を収集するのに比較的短い1 15秒かかりました。

これは、エントロピーの収集がCPU速度ベースではなく、ランダムイベントベースであり、Ubuntuシステムが重要なランダム要素の1つとしてマウスを使用していることを明確に示しています。

get=2048
trnd=/tmp/$USER.rnd; >"$trnd"
while (( $(wc -c <"$trnd") < $get )) ;do
    dd if=/dev/random bs=8 count=1 2>/dev/null >>"$trnd"
    echo -n "itt: $((i+=1))  ct: "; wc -c <"$trnd"
done
truncate -s $get "$trnd"
echo -e "\nfinal count: "; wc -c <"$trnd"

1

ddされて設計された、ブロッキングのために-それは通常、あなたの処分で最高のツールである可変サイズの入力から読み込みを行うためのあなたがそれを行う必要がある場合は、直ちにので、dd現在のバッファリングはありませんいくつかの未来に読み込むwrite() (あなたは非常に明確にIBSよりも大きなOBSでそのように設定しない限り)、しかし、代わりにwrite()、それが読み込まれるとすぐread()(そしてオプションでそれを処理する)すべてを読みます。

重要な定義を次に示します

  • ibs=expr
    • 入力ブロックサイズをバイト単位で指定します(デフォルトは512)expr
  • obs=expr
    • 出力ブロックサイズをバイト単位で指定します(デフォルトは512)expr
  • bs=expr
    • 両方の入力と出力ブロックサイズを設定しexpr、バイト取って代わるibs=obs=。より変換なし他の場合syncnoerrorおよびnotrunc指定され、各入力ブロックはショートブロックを集約することなく、単一のブロックとして出力にコピーされなければなりません。

あなたが見るので、ときibsobsとして一緒に定義されbs、その後ibs、あなたはどちらか、その後、特定されている場合は、そうでないが、 -優先されますobsか、cbsしません。

ibs最も重要な例を次に示します。/dev/randomプールがいっぱいになるのを追跡したい場合は、このようなことをするかもしれません...

dd "ibs=$size" conv=sync "count=$lmt" \ 
    if=/dev/random of="$somefile"

限りif=の目標は、すべての読み取り可能である、それはなります常にので、同じサイズの出力ファイルになりddますsyncブロックは、読み取りにヌルにhronize。つまり、dd read()入力ブロックのsがsで$((size=10)) $((count=5))read()ファイルが2バイト、8バイト、12バイト、2バイト、4バイトのいずれddかを返す場合、次のような出力ファイルに書き込みます。

 2 read bytes 8NULs \
 8 read bytes 2NULs \
10 read bytes 0NULs \
 4 read bytes 6NULs \
 4 read bytes 6NULs

... ddデフォルトでは遅延しませ。したがって、インストリームを追跡し、他のプロセスの書き込みを制限する必要がある場合、ddは、このツールがです。

一定量のデータを通常のファイルに書き込む場合、ここで行われた他のステートメントとは異なり、これにも使用できますdd-かなり簡単ですが-複数の信頼性の高いブロックファクターが必要になりますです。

たとえば、次の場合:

{   dd ibs="$size" obs="${size}x$block_factor" |
    dd bs="${size}x$blockfactor" "count=$lmt"
}  <infile >outfile

...最初のブロックは、そのブロックと2番目のブロックの間のパイプのすべてに対して少なくとも1つの出力ブロックを満たすために必要なdd数のibs="$size"入力ブロックをバッファリングします。これは、最初に行う必要があるsの数に関係なく、最初に作成するすべてのsがそのI / Oブロックサイズと一致するため、2番目の出力が確実に出力を制限できることを意味します。obs="${size}x$block_factor"write()ddddcount="$lmt"write()read()dd

そして、それddはパイプや他の種類の特殊ファイルをほんの少しの数学で確実に読み取るために使用できる方法です。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.