为什么 dd 无法处理 shell 脚本中的稀疏文件?
Why dd can't handle sparse files in shell scripts?
我有以下稀疏文件要闪存到 SD 卡:
647M -rw------- 1 root root 4.2G Sep 21 16:53 make_sd_card.sh.xNws4e
如您所见,它占用 ~647M 磁盘空间,表观大小为 4.2G。
如果我直接用dd
刷的话,在我的shell里面真的很快,~6s:
$ time (sudo /bin/dd if=make_sd_card.sh.xNws4e of=/dev/mmcblkp0 conv=sparse; sync)
8601600+0 records in
8601600+0 records out
4404019200 bytes (4.4 GB, 4.1 GiB) copied, 6.20815 s, 709 MB/s
real 0m6.284s
user 0m1.920s
sys 0m4.336s
但是当我在 shell 脚本中执行完全相同的命令时,它的行为就好像它正在复制所有的零并花费大量时间 (~2m10):
$ time sudo ./plop.sh ./make_sd_card.sh.xNws4e
+ dd if=./make_sd_card.sh.xNws4e of=/dev/mmcblk0 conv=sparse
8601600+0 records in
8601600+0 records out
4404019200 bytes (4.4 GB, 4.1 GiB) copied, 127.984 s, 34.4 MB/s
+ sync
real 2m9.885s
user 0m3.520s
sys 0m15.560s
如果我观看 /proc/meminfo
的 dirty 部分,我可以看到从 shell 脚本中 dd-ing 时该计数器比直接来自 shell.
我的shell是bash
备案,脚本是:
#!/bin/bash
set -xeu
dd if= of=/dev/mmcblk0 conv=sparse bs=512
sync
[编辑] 我重新讨论这个话题,因为与我一起工作的开发人员发现了这些命令:bmap_create
和 bmap_copy
这似乎用 dd 笨拙地做我正在尝试的事情。
在 debian 中,它们是 bmap-tools 包的一部分。
有了它,刷一个4.1GB的稀疏SD映像需要1m2s,实际大小为674MB,而使用dd或cp需要6m26s。
这种差异是由非脚本调用中的拼写错误造成的,它实际上并未写入您的存储卡。脚本调用和交互式调用之间的 dd
行为没有区别。
记住什么是稀疏文件是:它是文件系统上的一个文件,能够存储元数据跟踪哪些块具有值[=32] =],因此零块从未在磁盘上分配任何存储空间。
这个稀疏文件的概念特定于文件。你不能有稀疏块设备。
你这两行代码的区别在于其中一行(快的)有一个错字(mmcblkp0
而不是mmcblk0
),所以它指的是一个不存在的块设备名称。 因此,它创建了一个文件。文件可以是稀疏的。因此,它创建了一个稀疏文件。创建稀疏文件很快。
另一个,没有错字,写到块设备。块设备不能稀疏。因此,它总是需要完整的执行时间 运行.
我有以下稀疏文件要闪存到 SD 卡:
647M -rw------- 1 root root 4.2G Sep 21 16:53 make_sd_card.sh.xNws4e
如您所见,它占用 ~647M 磁盘空间,表观大小为 4.2G。
如果我直接用dd
刷的话,在我的shell里面真的很快,~6s:
$ time (sudo /bin/dd if=make_sd_card.sh.xNws4e of=/dev/mmcblkp0 conv=sparse; sync)
8601600+0 records in
8601600+0 records out
4404019200 bytes (4.4 GB, 4.1 GiB) copied, 6.20815 s, 709 MB/s
real 0m6.284s
user 0m1.920s
sys 0m4.336s
但是当我在 shell 脚本中执行完全相同的命令时,它的行为就好像它正在复制所有的零并花费大量时间 (~2m10):
$ time sudo ./plop.sh ./make_sd_card.sh.xNws4e
+ dd if=./make_sd_card.sh.xNws4e of=/dev/mmcblk0 conv=sparse
8601600+0 records in
8601600+0 records out
4404019200 bytes (4.4 GB, 4.1 GiB) copied, 127.984 s, 34.4 MB/s
+ sync
real 2m9.885s
user 0m3.520s
sys 0m15.560s
如果我观看 /proc/meminfo
的 dirty 部分,我可以看到从 shell 脚本中 dd-ing 时该计数器比直接来自 shell.
我的shell是bash
备案,脚本是:
#!/bin/bash
set -xeu
dd if= of=/dev/mmcblk0 conv=sparse bs=512
sync
[编辑] 我重新讨论这个话题,因为与我一起工作的开发人员发现了这些命令:bmap_create
和 bmap_copy
这似乎用 dd 笨拙地做我正在尝试的事情。
在 debian 中,它们是 bmap-tools 包的一部分。
有了它,刷一个4.1GB的稀疏SD映像需要1m2s,实际大小为674MB,而使用dd或cp需要6m26s。
这种差异是由非脚本调用中的拼写错误造成的,它实际上并未写入您的存储卡。脚本调用和交互式调用之间的 dd
行为没有区别。
记住什么是稀疏文件是:它是文件系统上的一个文件,能够存储元数据跟踪哪些块具有值[=32] =],因此零块从未在磁盘上分配任何存储空间。
这个稀疏文件的概念特定于文件。你不能有稀疏块设备。
你这两行代码的区别在于其中一行(快的)有一个错字(mmcblkp0
而不是mmcblk0
),所以它指的是一个不存在的块设备名称。 因此,它创建了一个文件。文件可以是稀疏的。因此,它创建了一个稀疏文件。创建稀疏文件很快。
另一个,没有错字,写到块设备。块设备不能稀疏。因此,它总是需要完整的执行时间 运行.