考虑一个100MB的原始块设备作为简单示例。即204800个块,每个块512个字节,总计102760448个字节。
面临的挑战是转移前98MB(200704块),使其前面有2MB(4096个块)的间隙。要就地执行此操作,需要将任何内容都写入未读取的扇区。实现此目的的一种方法是引入缓冲区:
$ dd if=/dev/sdj2 count=200704 | mbuffer -s 512 -b 4096 -P 100 | dd of=/dev/sdj2 seek=4096
期望mbuffer
在将任何内容传递给写入器之前将存储4096个块,从而确保未写入任何内容到尚未读取的区域,并且写入器落后于读取器缓冲区大小。缓冲区应允许读取器和写入器在这些内存中尽可能快地操作。
但是,它似乎无法可靠地工作。我曾尝试使用真实的设备,但是它永远无法在它们上运行,而使用文件进行的实验只能在我的64位设备上运行,而不能在我的32位设备上运行。
首先,做一些准备:
$ dd if=/dev/sdj2 count=200704 | md5sum
0f0727f6644dac7a6ec60ea98ffc6da9
$ dd if=/dev/sdj2 count=200704 of=testfile
这不起作用:
$ dd if=/dev/sdj2 count=200704 | mbuffer -s 512 -b 4096 -P 100 -H | dd of=/dev/sdj2 seek=4096
summary: 98.0 MiByte in 4.4sec - average of 22.0 MiB/s
md5 hash: 3cbf1ca59a250d19573285458e320ade
这适用于64位系统,但不适用于32位系统:
$ dd if=testfile count=200704 | mbuffer -s 512 -b 4096 -P 100 -H | dd of=testfile seek=4096 conv=notrunc
summary: 98.0 MiByte in 0.9sec - average of 111 MiB/s
md5 hash: 0f0727f6644dac7a6ec60ea98ffc6da9
如何可靠地做到这一点?
笔记
我看了一下缓冲等问题,看了看pv
,buffer
和mbuffer
。我只能让后者使用所需的缓冲区大小。
使用中间存储是解决始终存在的问题的明显方法,但是在没有足够的备用容量时不可行。
测试运行带有mbuffer
版本20140302的Arch Linux的平台。
mbuffer
实际上应该迫使第二dd
落后于第一,你只需要足够的内存来缓存移位的大小。太糟糕了dd
,不支持按向后顺序读取和写入块,因为这样可以消除问题!
-H
参数启用此功能)。
mbuffer
?为什么不dd
使用一次性读取块设备的全部内容dd bs=102760448
呢?当然,一种或另一种方式将其缓冲在RAM中。