#前言
本文是对 KMnO4y_Fish 的博文 [基础预科] Android 分区、启动模式、Fastboot 的一个补充。如您所见,此文成于 2022年1月,而谷歌在该年8月 Android 13 中加入的部分特性,导致了当前 Android 实际系统分区和此文所述有所出入。
#分区与 Linux
硬盘分区是指将硬盘的整体存储空间划分成多个独立的区域,每个区域可以用来安装操作系统、应用程序以及存储数据文件等。
在 Windows 下使用磁盘管理或 diskpart,或在 Linux 发行版下使用 fdisk/cfdisk 可以查看并操作设备分区。
$ sudo fdisk -l
Disk /dev/vda: 40 GiB, 42949672960 bytes, 83886080 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: gpt
Disk identifier: [Partition UUID]
Device Start End Sectors Size Type
/dev/vda1 227328 83886046 83658719 39.9G Linux filesystem
/dev/vda14 2048 10239 8192 4M BIOS boot
/dev/vda15 10240 227327 217088 106M EFI System
Partition table entries are not in disk order.Linux 秉持“一切设备皆文件”的设计理念,各种正常接入系统的硬件都能在 /dev 目录下找到,比如部分情况下磁盘的路径为 /dev/sdX 1,磁盘上的分区会在磁盘名后冠以数字表示该磁盘上的不同分区,比如本例中的 /dev/vda1。
与Windows不同,Linux没有盘符的概念,只有根目录(root directory)/,要访问分区内的文件,需要将设备挂载为根目录下的一个目录。同时,挂载也可以被看成是打开分区的操作,因而有不同的打开方式,常见的有只读(r/o,不能写入)、读写(r/w)和装入内存盘(可以写入,断电或重启时丢弃更改)。
sudo mount /dev/nvme0n1p1 /mnt由于 Android 基于 Linux 内核,本文仅介绍 Linux 系统下的磁盘分区特性。
#Android 分区
不同的 Android 设备具有不同的分区表,其具体分区也不太一样。此处列出 Android 13+ 部分常见分区。
| 分区名 | 挂载路径 | 用途 |
|---|---|---|
| boot | - | 系统内核、根文件系统 (rootfs) |
| init_boot | - | 启动镜像 (ramdisk / initramfs) |
| abl/lk | - | 启动引导程序 |
| system | /system | 此分区包含 Android 系统框架 |
| system_ext | /system_ext | AOSP 系统模块,OEM 或 SoC 专用模块 |
| product | /product | OEM (原始设备制造商)自定义镜像 |
| recovery | - | 恢复模式启动镜像,结构与boot相同 |
| cache | /cache | 缓存 |
| userdata | /data | 用户数据 |
| odm | /odm | 制造商 (ODM) 对系统芯片 (SoC) 供应商板级支持包 (BSP) 的自定义设置 |
| dtbo | - | 设备树覆盖文件分区 (Device Tree Blob Overlay) |
| vbmeta | - | 包含安全启动验证数据,通常在刷入非官方镜像前需要禁用vbmeta以防止无法启动导致黑砖 |
| odm_dlkm | - | 存储 ODM 内核模块,使得无需更新 odm 分区即可更新 ODM 内核模块。 |
| vendor | /vendor | 包含厂商私有的二进制文件以及驱动等 |
| vendor_boot | - | 包含启动时所需供应商信息和设备树 |
| vendor_dlkm | - | 存储供应商内核模块 |
| tos | - | 存储 Trusty (TEE) 操作系统的二进制映像文件 |
| pvmfw | - | 存储受保护的虚拟机固件 |
| model/radio | - | 包含无线装置映像,实现通讯功能 |
| *_cow | - | 临时分区,确保更新时异常断电不会造成老分区损坏,刷入不同ROM前通常需要删除 |
#A/B 分区
Android 有两种更新机制:A/B(无缝)更新和非 A/B 更新(A-Only);A/B 更新又分为两种,一种是AB分区,一种是VAB分区。
A/B 分区即划分两块分区(分别称为a、b槽位)给一特定的分区镜像。过去安卓更新需要进入 recovery 模式刷入镜像,需要在该模式下耗费大量时间,期间用户无法使用手机;而 A/B 分区使得现代 Android 在不影响用户使用的情况下后台刷写系统分区,无需进入 recovery,刷写完后重启并切换槽位便可完成系统更新,同时即使黑砖也能通过切换槽位恢复。
VAB分区相较于AB分区,使用了动态分区和快照技术。系统在更新时创建虚拟快照,允许后台更新并减少存储空间占用。笔者手上这台一加 Ace 5 便采用了这一技术。
#动态分区
动态分区是 Android 的用户空间分区系统,添加于 Android 10。使用此分区系统,您可以在无线下载 (OTA) 更新期间创建、销毁分区或者调整分区大小。借助动态分区,供应商无需担心各个分区(例如 system、vendor 和 product)的大小。取而代之的是,设备会分配一个 super 分区,其中的子分区可动态调整大小。各个分区映像不再需要为将来的 OTA 预留空间。相反,super 中剩余的可用空间还可用于所有动态分区。
super 大分区在不同厂商、不同启动模式下所包含的分区可能并不相同。通常情况下动态 A-Only 模式下 super 分区包含 system, vendor, product, odm, system_ext 等小分区,A/B 分区下会包含两套分区,而 VAB 分区下部分小分区只有一套。
⚠️ 注意
super 分区需要 FASTBOOT (BOOTLOADER) 模式下刷入,其包含的小分区可在 FASTBOOTD 模式下刷入。
刷入 super 分区或用 super_empty.img 清空 super 可能会改变分区大小,导致 FASTBOOTD 模式下无法直接刷入其他系统的小分区。如果此时没有原系统的 super(_empty) 分区,可能需要在手动删除并重新创建分区、调整分区大小后刷入。
实际上,由于分区大小不同,原厂系统本身可能也不能直接通过小分区刷入其他系统。
#参考
本文部分参考[基础预科] Android 分区、启动模式、Fastboot - KMnO4y_Fish、Android 分区详解 - Uotan Wiki · 刷机百科,遵循 CC-BY-NC-SA 4.0 协议。
- X可以是任意一个英文字母,用于区别不同磁盘;以nvme协议接入的磁盘还可能被冠以
/dev/nvmeXnY,此时X和Y可以是任意一数字;本例为一台云服务器的分区表,vd表示虚拟磁盘。 ↩