3. 动态分区核心概念

Android 10 引入动态分区(Dynamic Partitions)后,分区体系从“固定大小、固定用途”转向“按需分配、可动态调整”。理解动态分区,关键要抓住四个对象:物理分区、super 分区、逻辑分区,以及它们之间的映射关系。这四者构成了动态分区管理框架的骨架。

一、物理分区与 super 分区

物理分区是 GPT 分区表中真实存在的分区,例如 boot、init_boot、vendor_boot、dtbo、vbmeta、super、userdata、metadata 等。它们有确定的起始扇区和大小,由引导链直接读取。其中 super 是一个特殊的物理分区,它本身不承载文件系统,而是作为“容器”,内部再划分出多个逻辑分区。

super 分区是动态分区的物理载体。它的大小在分区表中固定,但内部空间由 liblp 元数据管理,可以灵活分配给 system、vendor、product、system_ext、odm 等逻辑分区。super 分区通常位于 userdata 之前,大小在编译时由 BoardConfig 中的 BOARD_SUPER_PARTITION_SIZE 决定。

super 分区 = 物理容器;逻辑分区 = 容器内的可分配空间。物理分区大小固定,逻辑分区大小可随元数据变化。

二、逻辑分区与映射关系

逻辑分区是 super 分区内部通过元数据定义的区域,例如 system_a、system_b、vendor_a、product_a 等。它们没有独立的 GPT 条目,而是通过 dm-linear 设备映射暴露给内核和用户空间。逻辑分区支持 A/B 槽位,因此同一逻辑分区名会带 _a 或 _b 后缀。

逻辑分区与物理分区的映射关系由 liblp 元数据描述。元数据包含分区名、组名、起始扇区、大小、槽位等字段。启动时,init 读取 super 分区中的元数据,创建对应的 device-mapper 设备节点,最终挂载为 /system、/vendor 等目录。

对象 是否在 GPT 中 大小是否固定 典型示例 访问方式
物理分区 是 固定 boot、super、userdata 直接块设备
super 分区 是 固定 super 容器,不直接挂载
逻辑分区 否 可动态调整 system_a、vendor_a dm-linear 映射
分区组 否 组内共享空间 qti_dynamic_partitions 元数据管理

三、动态分区管理框架

动态分区管理框架由三层组成:元数据层、映射层和用户空间层。

  • 元数据层:liblp 负责读写 super 分区中的元数据,包括分区表、分区组、槽位信息。元数据有两个副本,分别位于 super 分区的开头和结尾,防止单点损坏。
  • 映射层:dm-linear 将逻辑分区的线性地址映射到 super 分区的物理扇区。内核通过 device-mapper 暴露 /dev/block/dm-N 设备节点。
  • 用户空间层:init、fs_mgr、fastbootd 负责解析元数据、创建映射、挂载分区。OTA 时 update_engine 通过 liblp 调整逻辑分区大小。

下面是一个简化的映射关系示意图,展示 super 分区内部逻辑分区如何映射到块设备:

super 分区内部逻辑分区与 dm-linear 映射 物理分区(GPT) boot / init_boot 固定大小 super 分区 物理容器,大小固定 userdata / metadata 固定大小 liblp 元数据(两个副本) 分区名 | 分区组 | 起始扇区 | 大小 | 槽位 metadata 位于 super 头部与尾部 逻辑分区(super 内部) system_a 大小可调 vendor_a 大小可调 product_a 大小可调 system_ext_a 大小可调 dm-linear 映射层 /dev/block/dm-0 → /system /dev/block/dm-1 → /vendor /dev/block/dm-2 → /product /dev/block/dm-3 → /system_ext 关键点 super 是容器 逻辑分区可调 元数据双副本 dm-linear 映射 A/B 槽位后缀 分区组共享空间 fastbootd 调整 OTA 动态扩容

四、案例:OTA 时逻辑分区如何调整

假设设备当前 system_a 为 800MB,vendor_a 为 400MB,super 剩余空间 200MB。OTA 包需要将 system_a 扩展到 900MB。流程如下:

  1. update_engine 读取当前 super 元数据,确认剩余空间充足。
  2. 调用 liblp 修改 system_a 的起始扇区和大小,写入新元数据。
  3. 重新创建 dm-linear 映射,使 /dev/block/dm-0 指向新的扇区范围。
  4. 挂载新逻辑分区,写入 OTA 数据,完成后切换槽位。
# 查看 super 分区元数据(fastbootd 模式)
fastbootd
fastboot getvar super-partition-size
fastboot getvar partition-size:system_a

# 用户空间查看 dm 映射
adb shell dmctl list
adb shell ls -l /dev/block/dm-*

# 查看逻辑分区挂载
adb shell mount | grep -E "system|vendor|product"

五、常见误区与复盘

误区一:把 super 分区当成文件系统直接挂载。 super 分区本身没有文件系统,它只是容器,必须通过 liblp 元数据和 dm-linear 映射才能访问内部逻辑分区。
误区二:认为逻辑分区大小可以无限调整。 逻辑分区受 super 分区总大小和分区组剩余空间限制。如果组内空间不足,需要先缩小其他逻辑分区或调整分区组。
复盘建议: 调试动态分区问题时,优先确认三件事:super 分区大小是否足够、元数据是否损坏、dm-linear 映射是否成功创建。使用 lpdump 工具可以快速查看元数据内容。
# 使用 lpdump 查看 super 元数据
lpdump /dev/block/by-name/super

# 输出示例
Slot 0:
  Metadata version: 10.0
  Partition name: system_a
    Group: qti_dynamic_partitions_a
    Offset: 0x100000
    Size: 0x32000000
  Partition name: vendor_a
    Group: qti_dynamic_partitions_a
    Offset: 0x32100000
    Size: 0x19000000

掌握物理分区、super 分区、逻辑分区和映射关系,是理解动态分区管理框架的基础。后续的 Virtual A/B、OTA 更新、fastbootd 操作,都建立在这套映射模型之上。