文章目录
定义
结构
传统分区结构
bootloader
设备启动后,会先进入bootloader程序,判断开机时的按键组合(也会有一些其他判断条件,暂不赘述)选择启动到哪种模式,主要有Android系统、recovery模式、fastboot模式等。
boot
kernel
ramdisk
包含有Android系统的kernel和ramdisk。如果bootloader选择启动Android系统,则会引导启动此分区的kernel并加载ramdisk,完成内核启动。
system
包含有Android系统的可执行程序、库、系统服务和app等。内核启动后,会运行第一个用户态进程init,其会依据init.rc文件中的规则启动Android系统组件,这些系统组件就在system分区中。将Android系统组件启动完成后,最后会启动系统app —— launcher桌面,至此完成Android系统启动。
recovery
包含recovery系统的kernel和ramdisk。如果bootloader选择启动recovery模式,则会引导启动此分区的kernel并加载ramdisk,并启动其中的init继而启动recovery程序,至此可以操作recovery模式功能(主要包括OTA升级、双清等)。
cache
主要用于缓存系统升级OTA包等。双清就是指对userdata分区和cache分区的清理。
misc
主要用于Android系统和bootloader通信,使Android系统能够重启进入recovery系统并执行相应操作。
userdata
用户存储空间。一般新买来的手机此分区几乎是空的,用户安装的app以及用户数据都是存放在此分区中。用户通过系统文件管理器访问到的手机存储(sdcard)即此分区的一部分,是通过fuse或sdcardfs这类用户态文件系统实现的一块特殊存储空间。
metedata
vendor
包含有厂商私有的可执行程序、库、系统服务和app等。可以将此分区看做是system分区的补充,厂商定制ROM的一些功能都可以放在此分区。
radio
tos
OTA升级流程
over-the-air technology
- Android系统收到服务端下发的OTA推送,将OTA包下载至cache分区。
- OTA包下载完成后,将向misc分区写入指令,表明下次启动时进入recovery模式并使用该OTA包进行升级。
- 重启手机。
- 重启后最先进入bootloader,bootloader会先判断按键组合、电源寄存器等,随后会读取misc分区的内容并解析。由于步骤2中已经向misc分区写入了指令,此处bootloader读取指令后会引导启动recovery系统。
- 进入recovery,读取cache分区中的OTA包,并解析其中的升级脚本,按照其指令对系统各个分区进行升级。如果recovery自身也需要升级,会在此过程中向system中写入recovery-from-boot.p文件,这是一个recovery升级所需要的patch。
- recovery会清除misc分区。
- 重启手机。
- 重启后最先进入bootloader,判断按键组合、电源寄存器、misc分区内容等,默认情况会启动Android系统,此时已经是OTA升级后的新版本系统。
- 新版本Android系统启动后,会检查是否存在recovery-from-boot.p文件,如果存在,则会对recovery进行升级。
A/B分区结构
与之对应,传统分区结构被称为non-A/B分区。
将系统分区分成了A和B两个槽(slot),手机启动时会选择A槽或者B槽启动,运行过程中仅使用当前槽位的分区。一旦当前运行的槽出现问题,系统仍可以选择另一个槽进行启动,从而保证系统良好的可用性。
升级
采用A/B分区结构,能够实现无缝升级。
- 用户正在运行A槽,此时收到OTA推送,则系统会在后台一边下载OTA数据,一边同时对B槽进行升级。当B槽系统升级完成,用户会收到重启提示,此时重启手机将自动切换到B槽的新版本系统。在此过程中,仅重启操作是会被用户感知的,这个重启与普通重启的耗时没有什么区别。
- 如果OTA失败,也仅仅是待升级的槽出现问题,可以重新尝试OTA,并不会影响用户当前运行的系统。
- 由于A/B分区结构可以实现一边从服务端获取OTA数据,一边直接写入待升级的槽,不需要临时存储OTA包的空间,因此不再需要在cache或userdata分区预留足够空间。
Google定义了A/B槽的几种标识:
- bootable:标识该槽的系统是否可以启动。有时也用unbootable来标识(例如高通),含义与bootable相反。
- successful:标识该槽的系统是否成功启动过,仅当该槽系统能够启动、运行、进行OTA升级时,才会从用户态标记该槽为successful。
- active:标识该槽是否是当前运行的系统,两个槽中只有一个能标记为active。
系统重启后,在zygote启动前,init会调用update_verifier服务通过dm-verity机制校验本次升级的镜像,通过后则会被标记为successful。如果系统当前active的槽反复多次启动都没能标记为successful,则将该槽标记为unbootable,并将另外一个槽标记为active。
bootloader
功能同non-A/B的bootloader,只是此处会根据A/B槽的bootable、successful、active等标识来选择启动哪个槽。根据不同厂商的实现,可以是唯一的不区分A/B的bootloader,也可以自定义,例如高通的实现bootloader是由唯一的pbl(此分区无法擦写)来选择A/B槽,启动xbl_a/xbl_b,再启动abl_a/abl_b。
boot_a/boot_b
包含kernel和recovery的ramdisk。recovery打包在boot分区中,则不再需要recovery分区。并且recovery系统也不再负责OTA升级(由Android系统中update_engine服务负责),仅负责双清等其他操作。
system_a/system_b
功能同non-A/B的system分区,只是区分了A和B两个槽。
vendor_a/vendor_b
功能同non-A/B的vendor分区,只是区分了A和B两个槽。
userdata
功能同non-A/B的userdata,并且用户数据仅存储一份,不区分A/B。
misc
功能同non-A/B的misc,不区分A/B。
persist
用来存储一些持久化数据,不会随着双清、OTA等操作被清除。不区分A/B。
相关命令
分区结构
adb shell getprop ro.build.ab_update
查询设备是否采用 A/B 分区,如果结果显示 true 表示使用 A/B 分区,如果没有返回内容或者返回空白则不是 A/B 分区
adb shell getprop ro.boot.slot_suffix
查询当前是哪个分区(a、b、ab)
内存使用
adb shell cat /proc/meminfo
查看内存使用情况
adb shell cat dumpsys meminfo
查看各应用的内存使用情况
两者获取到的可用内存会有出入,这是正常的,因为后者中的Free Ram大致等于前者的MemFree+Buffers+Cached