4. 分区布局设计:Android/Linux 分区的门道
分区布局这事儿,看着像是个体力活——不就是划几个区嘛。但我在项目里栽过跟头之后才明白,分区规划做不好,后面调试能让你怀疑人生。今天咱们就聊聊典型的分区布局、大小怎么定,以及动态分区和超级分区到底解决了什么问题。
4.1 典型 Android/Linux 分区布局
先看一张经典的分区布局图,这是大多数 Android 设备的基础框架。
这张图里每个分区都有它的使命。我简单说一下:
- Bootloader 分区:存放引导加载程序。芯片上电后第一个跑的就是它。我见过不少设备因为 Bootloader 分区被误擦,直接变砖。
- Boot 分区:内核 + ramdisk。Bootloader 加载完内核后,内核挂载 ramdisk 作为临时根文件系统。
- System 分区:Android 系统本体。所有系统应用、框架、库都在这里。
- Vendor 分区:硬件厂商的驱动和 HAL。把厂商代码和系统代码分开,方便 OTA 升级。
- Data 分区:用户数据。应用安装、用户设置、数据库全在这。
- Cache 分区:OTA 升级缓存、系统临时文件。现在很多设备已经不用独立 cache 了。
- 辅助分区:Misc(启动控制)、Recovery(恢复模式)、Logo(开机动画)、Persist(校准数据)等。
我的习惯: 调试阶段我会把 Boot 和 Recovery 分区各留一个备份分区。万一刷坏了,还能从备份启动。这招救过我两次。
4.2 分区大小规划原则
分区大小怎么定?这不是拍脑袋的事。我总结了几条原则:
4.2.1 按功能需求估算
| 分区 | 典型大小 | 规划依据 |
|---|---|---|
| Bootloader | 2MB ~ 8MB | 取决于芯片平台,高通通常 4MB,MTK 可能 2MB |
| Boot | 32MB ~ 64MB | 内核大小 + ramdisk 大小,预留 20% 余量 |
| System | 1GB ~ 4GB | Android 版本越高越大,Android 13 的 GSI 约 2.5GB |
| Vendor | 256MB ~ 1GB | 厂商驱动 + HAL + 配置文件,看硬件复杂度 |
| Data | 剩余全部 | 用户数据是刚需,能大则大 |
| Cache | 0 ~ 256MB | 动态分区下可省略,传统布局建议 128MB |
这些数字不是死的。我记得有个项目,客户非要塞一堆预装应用,System 分区从 2GB 涨到 4GB 还不够。后来我建议用动态分区,才解决了这个问题。
4.2.2 对齐与边界约束
分区起始地址必须对齐到物理擦除块大小。NAND Flash 通常是 128KB 或 256KB,eMMC 是 512B 或 4KB。不对齐的话,擦写效率会大打折扣。
我曾经踩过的坑: 有个项目分区起始地址没对齐到 1MB 边界,结果 OTA 升级时擦写操作频繁触发全块擦除,升级时间从 5 分钟变成了 25 分钟。用户差点退货。
4.2.3 预留余量
分区大小 = 当前需求 × 1.2 ~ 1.5。为什么?因为 OTA 升级需要临时空间,系统更新后镜像可能变大。我一般给 System 和 Vendor 各留 30% 余量。
4.3 动态分区与超级分区
传统分区有个硬伤:分区大小在烧录时就固定了。System 分区不够用?只能重新分区、重新烧录。Android 10 之后引入了动态分区,说白了就是把多个逻辑分区塞进一个物理分区里。
4.3.1 动态分区解决了什么?
- 空间灵活分配:System、Vendor、Product 等分区共享一个物理分区池。哪个分区需要空间,就从池子里划。
- OTA 更安全:升级时可以用 COW(写时复制)机制,只修改变化的部分。
- 减少分区数量:物理分区从十几个减少到几个,分区表更清爽。
4.3.2 超级分区(Super)
超级分区是动态分区的物理载体。它本身是一个大的物理分区,内部通过逻辑卷管理(LVM)的方式划分出 system、vendor、product 等逻辑分区。
4.3.3 动态分区的关键概念
| 概念 | 说明 |
|---|---|
| Super 分区 | 物理分区,包含所有动态逻辑分区 |
| 逻辑分区 | system、vendor、product 等,大小可调 |
| COW 分区 | 写时复制分区,用于 OTA 升级时的增量写入 |
| Group | 逻辑分区的分组,如 default、google_dynamic_partitions |
| Metadata | 描述逻辑分区布局的元数据,存储在 Super 分区头部 |
动态分区调试要点:
- Bootloader 必须支持读取 Super 分区的 metadata,才能找到逻辑分区的实际位置。
- 如果 metadata 损坏,所有逻辑分区都不可见。我建议在 Bootloader 中保留一份 metadata 备份。
- 动态分区下,fastboot flash system 不再直接写物理分区,而是通过 fastbootd 在用户空间处理。
4.4 分区布局的避坑指南
最后分享几个我亲身经历的教训:
- 分区表不要写死:用 GPT 分区表,别用 MBR。GPT 支持更多分区、更大容量,而且有备份分区表。
- Bootloader 分区要写保护:量产时把 Bootloader 分区设为只读。我见过用户 root 后误擦 Bootloader,设备直接变砖。
- 预留救援分区:在分区表末尾留一个 64MB 的空白分区。万一需要紧急修复,这个分区可以用来放临时 recovery。
- 动态分区 metadata 要校验:每次修改 metadata 后计算 CRC32 或 SHA256。Bootloader 加载时先校验,校验失败就用备份。
我个人习惯: 在分区表里加一个 version 字段。每次调整分区布局后递增版本号。这样调试时一眼就能看出设备跑的是哪个版本的分区表,省去很多猜疑。
分区布局设计,说白了就是给系统画好地盘。画得太小,后面扩容麻烦;画得太大,浪费空间。动态分区虽然灵活,但增加了 Bootloader 的复杂度。选哪种方案,得看你的产品定位和团队能力。嗯,这块内容就聊到这儿,接下来你可以动手看看自己设备的分区表了。