当前位置: 首页 > news >正文

Android14 init.rc各个阶段的主要操作详解2

本博文主要介绍on late-fs阶段的主要操作。

1 on late-fs

late-fs阶段的整体目标:

目标实现方式
✅ 确保调试功能可用修复 tracefs 权限
✅ 启动关键 HALclass_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-fssetprop 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大小为1KBwrite /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分区已挂载,系统正式进入用户数据可访问阶段,核心目标是初始化数据分区、启动关键服务、结束“早期启动”阶段、为系统服务(如 keystoreapexd)准备运行环境。

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 分区的 mergecheckpoint 等操作
创建公共目录如 /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

http://www.dtcms.com/a/363078.html

相关文章:

  • 【Qt】bug排查笔记——QMetaObject::invokeMethod: No such method
  • 面试_Mysql
  • AdaBoost(Adaptive Boosting,自适应提升算法)总结梳理
  • 04 创建Centos 7操作系统
  • 基于ZooKeeper实现分布式锁(Spring Boot接入)及与Kafka实现的对比分析
  • 【Vue2 ✨】 Vue2 入门之旅(六):指令与过滤器
  • React 中 key 的作用
  • Rust SQLx 开发指南:利用 Tokio 进行性能优化
  • Spring Security资源服务器在高并发场景下的认证性能优化实践指南
  • FPGA AD7606串行驱动与并行驱动
  • AI如何理解PDF中的表格和图片?
  • 【HarmonyOS 6】仿AI唤起屏幕边缘流光特效
  • 使用Java获取本地PDF文件并解析数据
  • Echarts自定义横向柱状图中单条bar的样式
  • 从模态融合到高效检索:微算法科技 (NASDAQ:MLGO)CSS场景下的图卷积哈希方法全解析
  • 九月科技瞭望:中国科技发展规划动态洞察
  • DevExpress WPF中文教程:如何将WPF数据网格绑定到本地数据库?
  • Python 2025:量子计算、区块链与边缘计算的新前沿
  • [Linux]学习笔记系列 -- mm/swap.c 交换机制(Swap Mechanism) 物理内存的虚拟扩展
  • Linux92 shell:倒计时,用户分类
  • 【JavaEE】多线程案例
  • 删除⽂件之git
  • 前端20个高效开发的JS工具函数
  • 《水浒智慧》第二部“英雄是怎么炼成的”(下篇)读书笔记
  • 宋红康 JVM 笔记 Day11|直接内存
  • 怎么用redis lua脚本实现各分布式锁?Redisson各分布式锁怎么实现的?
  • Higress云原生API网关详解 与 Linux版本安装指南
  • lua脚本在redis中如何单步调试?
  • docker 安装 redis 并设置 volumes 并修改 修改密码(二)
  • MATLAB矩阵及其运算(四)矩阵的运算及操作