2、系统分区布局:Bootloader分区、Boot A/B分区、System A/B分区、Vendor A/B分区、Data分区、Misc分区

分区布局是整个A/B升级方案的基石。说白了,就是你的系统盘该怎么切、每个分区放什么、谁跟谁互为备份。我见过不少团队,升级方案设计得天花乱坠,结果分区表一画就露馅了——要么空间不够,要么备份关系搞错。

今天咱们就把这七个关键分区掰开揉碎讲清楚。嗯,先从最底层的Bootloader说起。

2.1 Bootloader分区

Bootloader是硬件上电后第一个跑起来的软件。它不参与A/B升级的直接逻辑,但它的位置和大小决定了整个分区表的起点。

关键点:Bootloader分区通常放在存储设备的起始位置(LBA 0之后),大小固定,一般4MB~8MB就够用。

我个人习惯把Bootloader分区放在最前面,原因很简单:很多SoC的启动ROM会硬编码读取地址,你挪了位置它就不认了。我在项目中遇到过一款芯片,Bootloader必须从第1个扇区开始读,否则直接死机——嗯,那真是让人头大的问题。

Bootloader分区里放什么?

  • 一级引导程序(SPL/MLO)
  • 二级引导程序(U-Boot、LK等)
  • 设备树文件(有时会单独分区)
  • 启动参数(bootargs、bootcmd等)

注意:Bootloader分区不要做得太大。我见过有人给了64MB,结果里面就放了2MB的U-Boot,纯属浪费。记住,存储空间是寸土寸金的,尤其是eMMC容量有限的产品。

2.2 Boot A/B分区

Boot分区放的是Linux内核镜像(zImage/Image)和对应的设备树。A/B双备份,意味着你有两个Boot分区:Boot_A和Boot_B。

为什么Boot也要做A/B?你想想看,如果内核坏了,系统根本起不来,那System分区再完整也没用。所以Boot分区必须跟System分区一起做冗余。

大小建议:每个Boot分区32MB~64MB。内核压缩后一般就几MB到十几MB,加上设备树,32MB绰绰有余。但我建议留点余量——我曾经遇到内核版本升级后体积膨胀了30%,差点撑爆分区。

分区 典型大小 内容
Boot_A 32MB~64MB 内核镜像 + 设备树
Boot_B 32MB~64MB 内核镜像 + 设备树(备份)

避坑指南:我曾经在项目里把Boot分区和System分区放在同一个物理块设备的不同区域,结果升级时Boot分区写坏了,整个设备变砖。后来我学乖了——Boot分区一定要有独立的坏块管理策略,或者干脆用两个不同的存储区域。

2.3 System A/B分区

System分区是Android/Linux系统的核心——所有系统应用、框架库、服务都在这里。A/B双备份,这是整个升级方案的核心。

System分区的大小取决于你的系统有多「胖」。纯AOSP可能只要1GB~2GB,加了GMS(Google Mobile Services)就要4GB以上,再塞点厂商定制应用,6GB~8GB也不稀奇。

我建议这样估算:

  • 先编译一个完整系统,看看system.img有多大
  • 乘以1.5倍作为安全余量
  • 再向上取整到最近的整数GB

举个例子:你的system.img是2.8GB,乘以1.5是4.2GB,那就给5GB。别抠抠搜搜的,分区空间不够了再改分区表,那可比多给1GB麻烦多了。

核心逻辑:升级时,系统往非活跃的System分区写入新版本。写入完成后,切换槽位标记。下次重启就从新分区启动了。

2.4 Vendor A/B分区

Vendor分区放的是硬件相关的驱动、HAL(硬件抽象层)库、固件等。为什么要把Vendor从System里拆出来?

原因很简单:硬件驱动更新频率跟系统框架不一样。你想想看,Wi-Fi芯片的固件可能一个月更新一次,但系统版本可能半年才升一次。如果都放在System分区里,每次升级都得全量更新,太浪费了。

Vendor分区的大小一般1GB~2GB就够。但要注意——有些厂商会把大量的预编译库塞进Vendor,比如相机算法库、音频处理库,那体积就不好说了。

我个人习惯把Vendor分区做成跟System分区一样的A/B结构。这样升级时可以独立更新驱动,不影响系统版本。

2.5 Data分区

Data分区是用户数据区——应用安装目录、用户设置、下载文件都在这里。它不参与A/B升级的直接逻辑,但升级过程中必须保证数据不丢失。

Data分区通常用F2FS或ext4文件系统。大小取决于产品定位:

  • 机顶盒/智能音箱:2GB~4GB
  • 手机/平板:16GB~128GB甚至更大
  • 工业设备:512MB~2GB(够用就行)

重要提醒:Data分区不做A/B备份。为什么?因为用户数据是动态变化的,你不可能维护两份用户数据。升级时,Data分区保持不变,只有System/Vendor/Boot这些系统分区才做切换。

但这里有个坑——升级过程中如果意外断电,Data分区可能损坏。所以一定要确保文件系统有日志功能(ext4默认有,F2FS也有),并且升级前做一次fsck检查。

2.6 Misc分区

Misc分区是个「小角色」,但缺了它还真不行。它用来存储一些元数据,比如:

  • 当前活跃的槽位(A还是B)
  • 升级状态标记(是否正在升级、是否升级完成)
  • 恢复模式标记(是否进入Recovery)

Misc分区很小,1MB~2MB就足够了。它通常用raw格式(不挂载文件系统),直接通过块设备读写。

我曾经在项目里遇到一个诡异的问题:升级完成后,设备反复重启。查了两天才发现——Misc分区里的槽位标记没写对,Bootloader读到的永远是旧槽位。从那以后,我每次写Misc分区都会做一次读回校验。

小技巧:Misc分区最好放在存储设备的末尾区域。因为分区表调整时,前面的分区大小变了,末尾的Misc分区不受影响。我习惯把Misc放在Data分区之后,紧挨着存储设备的最后一个LBA。

2.7 分区布局总览

好了,七个分区都讲完了。咱们画个总览图:

分区名称 备份方式 典型大小 文件系统 升级时是否更新
Bootloader 无备份 4MB~8MB raw 否(极少更新)
Boot_A / Boot_B A/B双备份 32MB~64MB × 2 raw 或 ext4
System_A / System_B A/B双备份 2GB~8GB × 2 ext4 或 erofs
Vendor_A / Vendor_B A/B双备份 1GB~2GB × 2 ext4 或 erofs
Data 无备份 视产品而定 F2FS 或 ext4
Misc 无备份 1MB~2MB raw 是(写标记)

看到没?真正做A/B备份的只有Boot、System、Vendor这三个分区。Bootloader和Misc是单份,Data也是单份。这样既保证了系统升级的安全性,又不会浪费太多存储空间。

嗯,分区布局这块就讲到这里。下一章咱们聊聊升级流程——从下载镜像到切换槽位,每一步是怎么走的。到时候我会结合代码示例,把整个流程串起来讲。