根本不理解 dd 命令参数
我对 dd 命令比较熟悉,但我自己很少需要使用它。今天我需要这样做,但我遇到了看起来很奇怪的行为。
我想创建一个100M的文本文件,其中每一行都包含一个单词“testing”。这是我的第一次尝试:
~$ 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
因此,在这四个表面上等效的命令中,所有命令都会生成不同大小的文件,其中只有一个是我期望的文件。这是为什么?
编辑:顺便说一句,我有点尴尬,我没有想到“是的测试”而不是那个更长的 Perl 命令。
I'm passingly familiar with the dd command, but I've rarely had the need to use it myself. Today I need to, but I'm encountering behavior that seems really weird.
I want to create a 100M text file, each line of which contains the single word "testing." This was my first try:
~$ 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
Hmm, that's odd. What about other combinations?
~$ 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
So of these four apparently-equivalent commands, all produce files of different sizes, only one of which is the one I would expect. Why is that?
EDIT: By the by, I'm a little embarrassed I didn't think of "yes testing" instead of that longer Perl command.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
要了解发生了什么,让我们看一下类似调用的
strace
的输出:发生的情况是
dd
生成单个read()< /code> 调用
来读取每个块。这适用于从磁带读取数据,而这正是 dd 最初的主要用途。在磁带上,
read
实际上读取一个块。从文件读取时,必须小心不要指定太大的块大小,否则读取
将被截断。从管道读取时,情况更糟:读取的块的大小将取决于生成数据的命令的速度。这个故事的寓意是不要使用 dd 来复制数据,除非是安全的小块。除了
bs=1
之外,绝不会来自管道。(GNU dd 有一个 fullblock 标志来告诉它行为得体。但其他实现则不然。)
To see what's going on, let's look at the output of
strace
for a similar invocation:What happens is that
dd
makes a singleread()
call to read each block. This is appropriate when reading from a tape, which is whatdd
was originally mainly used for. On tapes,read
really reads a block. When reading from a file, you have to be careful not to specify a too large block size, or else theread
will be truncated. When reading from a pipe, it's worse: the size of the block that you read will depend on the speed of the command producing the data.The moral of the story is not to use
dd
to copy data, except with safe, small blocks. And never from a pipe except withbs=1
.(GNU dd has a
fullblock
flag to tell it to behave decently. But other implementations don't.)我还不确定为什么,但使用此方法不会在保存之前填满整个块。尝试:
iflag=fullblock
似乎强制 dd 累积输入直到块已满,尽管我不确定为什么这不是默认值,或者默认情况下它实际上做了什么。I'm not yet sure why, but using this method will not fill up an entire block before saving it. Try:
The
iflag=fullblock
seems to force dd to accumulate input until the block is full, although I'm not sure why this is not the default, or what it actually does by default.我最好的猜测是 dd 从管道中读取,当它为空时,它假设它读取了整个块。结果很不一致:
My best guess is that
dd
reads from the pipe and when it's empty it assumes that it read the whole block. The results are quite inconsistent: