本博文主要介绍on late-fs阶段的主要操作。
1 on late-fs
late-fs阶段的整体目标:
目标 | 实现方式 |
---|---|
✅ 确保调试功能可用 | 修复 tracefs 权限 |
✅ 启动关键 HAL | class_start early_hal |
✅ 延伸系统信任链 | 加载 verity 保护的密钥 |
✅ 优化内存使用 | 禁用非必要 tracing |
1.1 设置tracefs权限
chmod 0755 /sys/kernel/tracing
chmod 0755 /sys/kernel/debug/tracing
tracefs
是内核用于 ftrace、systrace、perf 等调试和性能分析 的虚拟文件系统。- 路径
/sys/kernel/tracing
是tracefs
的挂载点 - 在较老的内核中,
tracefs
挂载在/sys/kernel/debug/tracing,
新内核迁移到/sys/kernel/tracing
,但为兼容性保留旧路径
1.2 启动class=early_hal的Services
class_start early_hal
常见的属于early_hal的Service有:system_suspend(wakelock锁屏后暂停所有服务),vendor-boot-hal各个服务,vendor-keymaster等。
1.3 加载可信秘钥(用于dm-verity)
exec -- /system/bin/fsverity_init --load-verified-keys
- 加载通过 dm-verity 或 fs-verity 验证的可信密钥到内核秘钥环(kernel keyring)。该指令是同步的,必须等到该指令执行完成并返回。
- dm-verity (Device-Mapper Verity):保护整个块设备分区(eg:/system)的完整性。用于A/B 更新、防回滚、防篡改。
- fs-verity(Filesystem Verity):保护单个文件的完整性(如 APK、密钥文件)。比
dm-verity
更细粒度,适合动态文件
1.4 禁用bootreceiver的tracking功能
# Don't enable the bootreceiver tracing instance to save 10MB of memory
on late-fs
setprop bootreceiver.enable 0
- 禁用
bootreceiver
组件的 tracing(追踪)功能,节省约 10MB 的运行时内存。 - bootreceiver是系统启动完成后,负责接收并处理
ACTION_BOOT_COMPLETED的广播机制。
2. 启用bootreceiver的tracking功能
- 条件:只有64bit的CPU架构,且bootreceiver.enable=1时才能执行。
- 作用:为
system_server
设置一个 tracing 实例,用于监控error_report_end
事件,进而记录日志、生成tombstone等。这些事件由 KASAN、KFENCE 等内核工具 在检测到内存损坏时发出。
on property:ro.product.cpu.abilist64=* && property:bootreceiver.enable=1
//创建bootreceiver的ftrace实例
mkdir /sys/kernel/tracing/instances/bootreceiver 0700 system system
//递归恢复该目录下的SELinux上下文
restorecon_recursive /sys/kernel/tracing/instances/bootreceiver
//设置该bootreceiver实例的ringbuffer大小为1KB
write /sys/kernel/tracing/instances/bootreceiver/buffer_size_kb 1
//当实例被free时,自动禁用tracking功能
write /sys/kernel/tracing/instances/bootreceiver/trace_options disable_on_free
//启用error_report事件的追踪
write /sys/kernel/tracing/instances/bootreceiver/events/error_report/error_report_end/enable 1
3 on post-fs-data
该阶段表示/data分区已挂载,系统正式进入用户数据可访问阶段,核心目标是初始化数据分区、启动关键服务、结束“早期启动”阶段、为系统服务(如 keystore
、apexd
)准备运行环境。
3.1 调用vold服务为checkpoint做准备
exec - system system -- /system/bin/vdc checkpoint prepareCheckpoint
Note: 在on post-fs阶段有exec - system system -- /system/bin/vdc checkpoint markBootAttempt操作,调用vold记录尝试启动,参考:Android14 init.rc各个阶段的主要操作详解1。
- vold:volume daemon(卷守护进程),路径在/system/bin/vold,源码在/system/vold,它在on early-fs阶段启动。主要功能:
功能 | 说明 |
---|---|
监听内核事件 | 接收来自内核的 uevent (如设备插入/拔出) |
管理存储卷 | 识别、挂载、卸载 /data 、/sdcard 、/mnt/media_rw/... 等 |
FDE/FBE 加密 | 管理全盘加密(FDE)和文件级加密(FBE)的密钥与解密 |
A/B 更新支持 | 处理 A/B 分区的 merge 、checkpoint 等操作 |
创建公共目录 | 如 /storage/emulated/0 (模拟的内部存储) |
提供 Binder 接口 | 供 system_server (如 MountService )调用 |
- vdc:volume daemon Client,路径在/system/bin/vdc,源码在/system/vold/vdc.cpp,它是一个命令行工具,用于向vold发送控制指令,eg: vdc checkpoint prepareCheckpoint。部分源码如下:
android::sp<android::IBinder> binder = getServiceAggressive();
if (!binder) {
LOG(ERROR) << "Failed to obtain vold Binder";
exit(EINVAL);
}
auto vold = android::interface_cast<android::os::IVold>(binder);
if (args[0] == "cryptfs" && args[1] == "enablefilecrypto") {
checkStatus(args, vold->fbeEnable());
} else if (args[0] == "volume" && args[1] == "shutdown") {
checkStatus(args, vold->shutdown());
} else if (args[0] == "volume" && args[1] == "reset") {
checkStatus(args, vold->reset());
} else if (args[0] == "checkpoint" && args[1] == "prepareCheckpoint" && args.size() == 2) {
checkStatus(args, vold->prepareCheckpoint());
} else if (args[0] == "checkpoint" && args[1] == "markBootAttempt" && args.size() == 2) {
checkStatus(args, vold->markBootAttempt());
3.2 操作/data分区
包括:设置/data分区权限组为system,恢复SELinux上下文,
3.3 启动bootchart
- /data分区挂载后尽快启动bootchart来收集从/data挂载到boot完成的性能数据。
- bootchart:启动性能分析工具,记录启动过程中CPU、I/O、进程活动。
- encryption=Require:表示/data/bootchart目录必须在/data解密后才能访问。
mkdir /data/bootchart 0755 shell shell encryption=Require
bootchart start