14

私はddコマンドにすっかり慣れていますが、自分で使用する必要はほとんどありません。今日はそうする必要がありますが、本当に奇妙に思える行動に遭遇しています。

1億のテキストファイルを作成したいと思います。各行には「testing」という1つの単語が含まれています。これは私の最初の試みでした:

~$ perl -e 'print "testing\n" while 1' | dd of=X bs=1M count=100
0+100 records in
0+100 records out
561152 bytes (561 kB) copied, 0.00416429 s, 135 MB/s

うーん、それは奇妙だ。他の組み合わせはどうですか?

~$ perl -e 'print "testing\n" while 1' | dd of=X bs=100K count=1K
0+1024 records in
0+1024 records out
4268032 bytes (4.3 MB) copied, 0.0353145 s, 121 MB/s

~$ perl -e 'print "testing\n" while 1' | dd of=X bs=10K count=10K
86+10154 records in
86+10154 records out
42524672 bytes (43 MB) copied, 0.35403 s, 120 MB/s

~$ perl -e 'print "testing\n" while 1' | dd of=X bs=1K count=100K
102400+0 records in
102400+0 records out
104857600 bytes (105 MB) copied, 0.879549 s, 119 MB/s

したがって、これら4つの明らかに同等のコマンドのうち、すべてが異なるサイズのファイルを生成しますが、そのうちの1つだけが私が期待するものです。何故ですか?

編集:までに、私はその長いPerlコマンドの代わりに「はいテスト」を考えていなかったので少し恥ずかしいです。

4

3 に答える 3

9

strace何が起こっているかを確認するために、同様の呼び出しの出力を見てみましょう。

execve("/bin/dd", ["dd", "of=X", "bs=1M", "count=2"], [/* 72 vars */]) = 0
…
read(0, "testing\ntesting\ntesting\ntesting\n"..., 1048576) = 69632
write(1, "testing\ntesting\ntesting\ntesting\n"..., 69632) = 69632
read(0, "testing\ntesting\ntesting\ntesting\n"..., 1048576) = 8192
write(1, "testing\ntesting\ntesting\ntesting\n"..., 8192) = 8192
close(0)                                = 0
close(1)                                = 0
write(2, "0+2 records in\n0+2 records out\n", 31) = 31
write(2, "77824 bytes (78 kB) copied", 26) = 26
write(2, ", 0.000505796 s, 154 MB/s\n", 26) = 26
…

何が起こるかというとdd、各ブロックを読み取るために1回のread()呼び出しを行います。これは、ddもともと主に使用されていたテープから読み取る場合に適しています。テープでは、read実際にブロックを読み取ります。ファイルから読み取るときは、大きすぎるブロックサイズを指定しないように注意する必要があります。そうしないと、readが切り捨てられます。パイプから読み取る場合はさらに悪いことになります。読み取るブロックのサイズは、データを生成するコマンドの速度によって異なります。

dd話の教訓は、安全で小さなブロックを除いて、データのコピーに使用しないことです。そして、を除いてパイプから決してbs=1

(GNU ddには、fullblock適切に動作するように指示するフラグがあります。しかし、他の実装にはありません。)

于 2011-07-21T23:59:09.477 に答える
8

理由はまだわかりませんが、この方法を使用しても、保存する前にブロック全体がいっぱいになることはありません。試す:

perl -e 'print "testing\n" while 1' | dd of=output.txt bs=10K count=10K iflag=fullblock
10240+0 records in
10240+0 records out
104857600 bytes (105 MB) copied, 2.79572 s, 37.5 MB/s

iflag=fullblock、ブロックがいっぱいになるまでddに入力を蓄積させるようですが、これがデフォルトではない理由や、デフォルトで実際に何が行われるのかはわかりません。

于 2011-07-21T21:24:05.097 に答える
3

私の最善の推測はdd、パイプからの読み取りであり、パイプが空の場合は、ブロック全体を読み取ると想定します。結果はかなり一貫性がありません:

$ perl -e 'print "testing\n" while 1' | dd of=X bs=1M count=100
0+100 records in
0+100 records out
413696 bytes (414 kB) copied, 0.0497362 s, 8.3 MB/s

user@andromeda ~
$ perl -e 'print "testing\n" while 1' | dd of=X bs=1M count=100
0+100 records in
0+100 records out
409600 bytes (410 kB) copied, 0.0484852 s, 8.4 MB/s
于 2011-07-21T21:27:30.743 に答える