2. rootfs分区布局设计:双分区(A/B)方案、单分区+备份方案、分区表与挂载点规划

分区布局这事儿,说白了就是给系统找个「安全屋」。我做了这么多年嵌入式,见过太多因为分区设计不合理导致升级变砖的惨案。今天咱们就把这块硬骨头啃下来。

2.1 双分区(A/B)方案:工业级标配

双分区方案,也叫A/B分区。简单说就是准备两套完整的rootfs,一套运行,一套待命。我个人习惯叫它「影子系统」。

核心思想:任何时候都有两个可启动的系统副本。升级时写入备用分区,下次启动切换。

分区布局示例

/dev/mmcblk0p1  →  boot_a (内核+dtb)
/dev/mmcblk0p2  →  rootfs_a (系统A)
/dev/mmcblk0p3  →  boot_b (内核+dtb)
/dev/mmcblk0p4  →  rootfs_b (系统B)
/dev/mmcblk0p5  →  data (用户数据)
/dev/mmcblk0p6  →  misc (元数据)

我在项目中遇到过一个问题:某次升级写到一半断电了,系统A损坏。但因为有B分区,设备重启后自动回滚到B,用户完全无感。这就是双分区的价值。

工作流程

  1. 正常启动:uboot读取misc分区,决定从A还是B启动
  2. 升级触发:系统运行时,将新版本写入非活动分区
  3. 校验切换:写入完成后,更新misc分区标记,下次启动切换
  4. 回滚机制:如果新系统启动失败,uboot自动切回旧分区

避坑指南:我曾经遇到过misc分区写坏导致无法切换的情况。后来我强制要求misc分区使用独立物理块,并且每次写入前做CRC校验。嗯,这招很管用。

2.2 单分区+备份方案:轻量级选择

双分区虽好,但存储成本高。对于资源受限的设备(比如8MB Flash),单分区+备份方案更实际。

说白了就是:一个主分区跑系统,一个压缩包存备份。升级时先解压备份到临时区,再覆盖主分区。

典型布局

/dev/mtdblock0  →  bootloader (uboot)
/dev/mtdblock1  →  rootfs (主系统)
/dev/mtdblock2  →  backup (压缩的系统备份)
/dev/mtdblock3  →  config (配置参数)

升级流程

  1. 下载新固件到内存
  2. 将当前rootfs压缩备份到backup分区
  3. 擦除rootfs分区,写入新固件
  4. 重启验证
  5. 如果启动失败,从backup分区恢复

注意:单分区方案有个致命弱点——升级过程中断电,系统就挂了。你想想看,擦除一半断电,rootfs就没了。所以必须配合看门狗和掉电保护电路。

2.3 分区表与挂载点规划

分区表设计,我建议遵循「最小权限」原则。每个分区只挂载它需要的东西,别搞大杂烩。

推荐分区表

分区 大小 文件系统 挂载点 说明
boot 64MB ext4 /boot 内核、dtb、uboot环境
rootfs 512MB squashfs / 只读系统,防篡改
data 剩余 ext4 /data 用户数据、日志、配置
overlay 128MB ext4 /overlay overlayfs上层,可写

为什么rootfs用squashfs?因为它是只读的,能防止意外修改。我见过有人用ext4做rootfs,结果一次误操作rm -rf /,系统直接废了。squashfs就没这问题。

挂载点规划示例

# /etc/fstab
/dev/mmcblk0p1  /boot       ext4    defaults        0 0
/dev/mmcblk0p2  /           squashfs ro              0 0
/dev/mmcblk0p3  /data       ext4    defaults        0 0
/dev/mmcblk0p4  /overlay    ext4    defaults        0 0
overlay         /           overlay lowerdir=/,upperdir=/overlay/upper,workdir=/overlay/work 0 0

个人经验:我习惯把日志和临时文件挂载到tmpfs上,减少对Flash的写入。比如/var/log用tmpfs,重启就清空,省心。

2.4 核心逻辑流程图

下面这张图,是我自己总结的分区决策流程。你一看就明白什么时候该用哪种方案。

rootfs分区方案决策流程 开始设计分区 存储 > 1GB? 是 双分区A/B 工业级可靠 否 需要回滚? 是 单分区+备份 需掉电保护 否 单分区无备份 风险较高 确定分区表与挂载点

2.5 避坑总结

做了这么多年,我踩过的坑能写本书。这里挑几个最要命的说说:

  • 分区大小别卡太死:我曾经给rootfs只留了256MB,结果一次日志暴涨直接撑爆。现在我都留30%余量。
  • uboot环境变量要备份:有一次升级把uboot环境搞乱了,设备变砖。后来我强制要求环境变量存两份。
  • 挂载顺序有讲究:overlayfs必须先挂载底层,再挂载上层。顺序错了系统都起不来。

最后提醒一句:分区设计不是一劳永逸的。产品迭代过程中,分区大小、布局都可能需要调整。我建议在硬件设计阶段就预留分区扩展接口,比如用GPT分区表而不是MBR,方便以后调整。

好了,分区布局这块就聊到这儿。下一章咱们聊聊升级包的制作和签名,那又是另一番天地。

可可精品资料库