为什么 dd 需要太长时间?

为什么 dd 需要太长时间?

我需要将一个磁盘复制到另一个磁盘。我尝试使用下面的命令,在 federo 中复制 1 TB 磁盘需要将近一天的时间。

dd if=/dev/sda of=/dev/sdb 

我在 Unix(HP-UX) 系统上使用下面的命令尝试了相同的操作,它在几个小时内完成

dd if=/dev/sda of=/dev/rdsk

我可以使用什么替代方法来更快地从磁盘复制到磁盘?

答案1

dd有很多(奇怪的)选项,请参阅日(1)

您应该明确说明缓冲区大小,因此请尝试

dd if=/dev/sda of=/dev/sdb bs=16M

IIRC,默认缓冲区大小仅为 512 字节。上面的命令将其设置为 16 MB。您可以尝试更小的东西(例如bs=1M),但您应该使用比默认值更多的东西(特别是在具有 4Kbytes 扇区的最新磁盘硬件上,即高级格式)。我天真地推荐一些至少是一兆字节的二的幂。

使用默认的 512 字节缓冲区大小,我猜想(但我可能是非常错误的)硬件要求内核为每个 512 字节块传输 4K。

关于rdsk标准差(4)手册页说:

此时仅提供块设备。原始设备尚未实现。

增加 dd 的缓冲区大小将为您提供更好的读写操作性能。现在所有磁盘都有硬件读/写缓冲区。但是,如果将 dd 的缓冲区大小增加到超过硬件缓冲区,则其性能将会下降,因为当第二个磁盘从其自己的硬件缓冲区写入所有内容时,dd 将从第一个磁盘读取到缓冲区。您需要bs每次为不同的设备设置不同的 dd 命令选项。

答案2

多年前,在 Unix 领域,dd复制块设备是必需的方法。尽管(至少在基于 Linux 的系统上)cat几乎总是比dd.

然而,即使在历史上,考虑到每个系统调用都会触发一个 I/O 操作,适当的块大小也有助于减少(缓慢)系统调用的数量。默认块大小为 512 字节(一个磁盘扇区)。将多个磁盘块收集在一起进行一次读取过去也是可以接受的。此示例使用 32MB 块大小:

dd bs=$((512*2048*32)) if=/dev/source of=/dev/target

顺便说一句,如果您正在读取未压缩的流或来自远程网络源的流,您可能会发现短读取小于所需的块大小。这些应该通过告诉dd重新读取直到获得足够的输入来填充块来处理,iflag=fullblock;如果没有这个,您有时可能会得到损坏的输出流。这里的情况并非如此,但为了完整性我将其包括在内。

回到最初的问题,在当前基于 Linux 的系统上,可以通过简单的方法最有效地复制磁盘cat

cat /dev/source >/dev/target

(正如您的问题的评论中所指出的,pv可以替换它cat,并为您提供进度和吞吐量的指示。)

答案3

一般来说,dd可以避免使用某些替代方案。使用 GNU 来代替有几个很好的理由ddrescue。在 Ubuntu 中,您可以使用以下命令安装它:

sudo apt-get install gddrescue

简单地说ddrescue易用。请注意,与包名称不同,可执行文件才不是有初始g.

使用它非常简单:

ddrescue inputFile outputFile logFile

日志文件(无论您选择什么名称)都可以让您暂停/停止和重新启动,而无需重做之前的工作,这在进行大型克隆或磁盘恢复时非常有用。默认情况下,它显示进度、当前复制速度、平均复制速度和发现的坏块数量。

它对块大小使用合理的默认值,因此复制速度始终与设备可以处理的速度一样快,至少根据我的经验(我已经用它克隆了数百个驱动器,所有大小和类型)。

通常,开始出现故障的驱动器会出现速度问题,例如偶尔出现速度缓慢、平均速度较低、突然长时间暂停(坏扇区)或完全重置(严重的表面错误)。ddrescue即使您的驱动器正在自行重置,也可以帮助您识别上述所有内容并重新启动克隆(前提是您指定了日志文件)。

答案4

非常好的问题。原始接口在某些 UNIX 系统(tru64、hpux、solaris)上实现,但在 Linux 上未实现。原始接口使传输速度更快,因为跳过了 UNIX I/O。块接口(/dev/dsk/dev/disk)速度较慢,因为它使用 unix I/O 系统。要加速dd(gnu dd 可以)使用bs=30M或 ,bs=20M具体取决于您的硬件。简短的回答是:不,至少据我所知,它还没有实施。我从内核版本 2.2 的旧时代开始就使用 Linux,从未见过rdsk在 UNIX 上使用过。

相关内容