使用dd写入带空洞的Buildroot镜像至eMMC导致内核恐慌的问题
问题描述
我用dd工具将Buildroot生成的镜像刷入单板计算机(SBC)的eMMC(以大容量存储设备形式连接),该镜像是通过genimage创建的,内部包含“空洞”。
genimage配置文件(genimage.cfg)
image sdcard.img { hdimage { } partition u-boot { bootable = true image = "u-boot.bin" size = 2M in-partition-table = false offset = 0 holes = {"(440; 512)"} } partition rootfsA { partition-type = 0x83 image = "rootfs.ext2" offset = 3M } partition data { partition-type = 0x83 image = "data.ext2" } } image data.ext2 { name = "data" ext4 { label = "data" } srcpath = "/home/<user>/buildroot_radxa/buildroot-2022.11/my_files/data_partition" size = 32MB }
异常现象
- 写入速度远低于设备最大值(约5MB/s,峰值仅20MB/s)
dd写入完成后文件系统损坏,触发内核恐慌- 第二次尝试写入时,几秒内完成,速度高达GB/s
- 极少数情况下能正常刷入并运行
使用的dd命令
sudo dd if=$img_path of=/dev/sdd status=progress bs=1024 conv=fsync
但用balenaEtcher刷入该镜像时,系统能完全正常运行。请问我遗漏了什么配置或操作?
问题分析与解决
核心问题是dd默认会处理镜像的全部字节(包括空洞),而balenaEtcher会智能跳过空洞、优化IO操作并正确处理缓存,以下是具体解决办法:
1. 跳过镜像空洞
genimage生成的是稀疏镜像,包含未写入数据的空洞。dd默认会把这些空洞转换成全0字节写入eMMC,既浪费时间,还可能导致缓存混乱、文件系统损坏。添加sparse=always参数可跳过空洞,只写入实际有数据的部分:
sudo dd if=$img_path of=/dev/sdd status=progress bs=1M sparse=always conv=fsync
2. 调整块大小提升速度
你使用的bs=1024(1KB)块大小过小,会触发大量IO操作,严重拖慢速度。建议设置为bs=1M或bs=4M,匹配eMMC的最优IO块大小,大幅提升写入效率。
3. 清理缓存避免干扰
写入前清空系统缓存,防止旧数据影响写入准确性:
sudo sync sudo echo 3 > /proc/sys/vm/drop_caches
写入完成后再执行一次sudo sync,确保所有数据都刷入硬件。
4. 确认设备与分区对齐
- 务必确认
/dev/sdd是目标eMMC设备,避免误写其他存储设备 - 你的genimage配置中分区偏移已符合4KB对齐要求(3M偏移对应768个4KB扇区),后续调整分区时需保持对齐
替代工具推荐
如果不想调整dd参数,可使用pv配合dd实现类似Etcher的可视化与高效写入:
sudo pv $img_path | sudo dd of=/dev/sdd bs=1M sparse=always conv=fsync
内容的提问来源于stack exchange,提问作者mister_kanister
相关产品推荐
相关产品推荐

