简介:dd是一个怪异的工具,很难正确使用。尽管有许多教程告诉您,但不要使用它。dd它具有“ unix street cred”的氛围-但如果您真正了解自己在做什么,就会知道不应该用10英尺长的杆子碰它。
ddread每个块(由的值定义bs)对系统调用进行一次调用。不能保证read系统调用返回的数据与指定的缓冲区大小一样多。这通常适用于常规文件和块设备,但不适用于管道和某些字符设备。请参阅dd什么时候适合复制数据?(或何时分别使用read()和write()部分)以获取更多信息。如果read系统调用返回少于一个完整的块,则dd传输一个部分块。它仍然会复制指定数量的块,因此传输的字节总数少于请求的数量。
关于“部分读取”的警告告诉您确切的信息:其中一个读取是部分读取的,因此dd传输了不完整的块。在块计数中,+1表示部分读取了一个块。由于输出计数为+0,因此所有块均被读取读取。
这不会影响数据的随机性:所有dd写出的字节都是从中读取的字节/dev/urandom。但是您得到的字节少于预期。
Linux可以/dev/urandom容纳任意大的请求(来源:extract_entropy_userin drivers/char/random.c),因此dd从它读取时通常是安全的。但是,读取大量数据需要时间。如果该进程收到信号,则read系统调用将在填充其输出缓冲区之前返回。这是正常现象,应用程序应该read循环调用。dd出于历史原因,它不这样做(dd的起源很模糊,但是它似乎最初是作为一种访问磁带的工具,这种磁带具有特殊的要求,并且从未适合用作通用工具)。当您检查进度时,这会向dd进程发送一个信号,该信号会中断读取。您可以选择知道多少个字节dd总共遗嘱副本(确保不中断它-不进行进度检查,不暂停),或知道多少字节dd 到目前为止已复制,在这种情况下,您不知道它将复制多少字节。
ddGNU coreutils中的版本(在非嵌入式Linux和Cygwin上可以找到)带有一个标志fullblock,该标志指示dd调用read循环(和相同write),因此始终传输完整的块。错误消息表明您正在使用它。您应该始终使用它(在输入和输出标志中),除非在非常特殊的情况下(通常在访问磁带时)—如果您完全使用它dd,那就是:通常有更好的解决方案(请参见下文)。
dd if=/dev/urandom iflag=fullblock oflag=fullblock of=file bs=1M count=1000000
确定执行该dd操作的另一种可能方法是传递一个块大小为1。然后,您可以知道从块计数中复制了多少字节,尽管我不确定read在读取第一个前a 被中断会发生什么。字节(实际上不太可能,但是可能发生)。但是,即使有效,这也非常慢。
关于使用的一般建议dd是不要使用dd。尽管dd通常将其宣传为访问设备的低级命令,但实际上并非如此:所有魔术都发生在设备文件(/dev/…)部分中,dd它只是一个普通的工具,极有可能被滥用,从而导致数据丢失。在大多数情况下,至少在Linux上,有一种更简单,更安全的方法来执行所需的操作。
例如,要读取文件开头的一定数量的字节,只需调用head:
head -c 1000000m </dev/urandom >file
我在我的机器上进行了快速基准测试,并没有观察到dd大块大小和大小的性能差异head。
如果您需要在开始时跳过一些字节,请tail输入head:
dd if=input of=output count=C bs=B seek=S
<input tail -c +$((S*B+1)) | head -c $((C*B)) >output
如果要查看进度,请致电lsof以查看文件偏移量。这仅适用于常规文件(示例中的输出文件),不适用于字符设备。
lsof -a -p 1234 -d 1
cat /proc/1234/fdinfo/1
您可以致电pv获取进度报告(优于dds),但要牺牲管道中的其他项目(就性能而言,这几乎是不可感知的)。