将映像写入磁盘的常用方法如下所示:
dd if=file.img of=/dev/device
在此命令之后,是否需要运行sync
?
sync(2)解释说它只刷新文件系统缓存。由于dd
命令与任何文件系统无关,因此我认为没有必要运行sync
。然而,块层是复杂和有疑问的,大多数人更喜欢运行sync
。
有没有人证明它是有用或无用的?
TL;DR:dd
后运行blockdev --flushbufs /dev/device
。
我试图遵循内核中的不同路径。以下是我的理解:
ioctl(block_dev, BLKFLSBUF, 0)
打电话给blkdev_flushbuf()
.考虑到它的名字,它应该刷新与设备关联的缓存(或者我认为您可以认为设备驱动程序中存在错误)。我认为它还应该负责刷新硬件缓存(如果存在)。注意e2fsprogs
使用BLKFLSBUF
。fdatasync()
(和fsync()
)将调用blkdev_fsync()
。它看起来像blkdev_flushbuf()
但它只影响当前进程写入的数据范围(它使用filemap_write_and_wait_range()
而BLKFLSBUF
使用filemap_write_and_wait
)。- 关闭块设备会调用不刷新缓冲区的
blkdev_close()
。 sync()
会打电话给sync_fs()
.它将刷新文件系统缓存并在底层块设备上调用fsync()
。- 命令
sync /dev/device
将在/dev/device
上调用fsync()
。但是,我认为这是无用的,因为dd
没有接触任何文件系统。
所以我的结论是,调用sync
对块设备没有(直接)影响。但是,将fdatasync
(或fsync
)传递给dd
是保证数据正确写入介质的唯一方法。
如果你跑dd
但错过了fdatasync
,跑sync /dev/device
是不够的。您必须在整个设备上运行dd
fdatasync
。或者,您可以调用BLKFLSBUF
来刷新整个设备。不幸的是,没有标准的命令。
编辑
您可以使用blockdev --flushbufs /dev/device
发出BLKFLSBUF
。
为了确保在拔出之前在 USB 设备上刷新数据,我使用以下命令:
echo 1 > /sys/block/${device}/device/delete
这样,数据将被刷新,如果设备是硬盘驱动器,则磁头将停放。