You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 11:24:57