Android 系统启动中 Init 进程第二阶段(second_stage)的核心逻辑,解析从安全初始化到系统服务启动的关键步骤:
一、第二阶段入口:SecondStageMain 函数的初始化
在完成 SELinux 初始化后,Init 进程通过 execv 带参数 second_stage 进入第二阶段,核心逻辑在 SecondStageMain 函数中执行。这一阶段的目标是:
- 完成系统属性初始化
- 启动进程监控机制
- 加载系统服务配置文件
- 为启动 Zygote、SystemServer 等核心服务做最终准备
二、关键步骤详解
1. 进程安全与优先级设置
-
注册崩溃重启信号:
与第一阶段类似,通过InstallRebootSignalHandlers监听致命信号(如 SIGABRT),开发模式下崩溃时直接重启到 Bootloader。 -
设置最高进程优先级:
c
WriteFile("/proc/1/oom_score_adj", "-1000");oom_score_adj是 Android 的进程优先级值,范围从 -1000(最高优先级)到 +1000(最低)。- Init 作为根进程,设置为 -1000 确保系统运行时始终保留,不会被内存管理机制杀死。
-
启用系统调用过滤(Seccomp) :
通过GlobalSeccomp()限制 Init 进程可用的系统调用,减少潜在安全风险(如禁止危险的内核操作)。
2. 系统标记与密钥管理
-
创建引导进行中标记:
c
close(open("/dev/.booting", O_WRONLY | O_CREAT | O_CLOEXEC, 0000));- 在
/dev下创建.booting文件,作为系统启动中的临时标记,供其他进程(如固件加载器)检测启动状态。
- 在
-
内核密钥服务初始化:
c
keyctl_get_keyring_ID(KEY_SPEC_SESSION_KEYRING, 1);- 调用内核密钥管理接口,为后续加密操作(如文件加密 FBE)准备密钥缓存,确保安全上下文的密钥可用。
3. 属性系统:Android 的「全局配置中心」
属性系统是 Android 中存储全局配置的核心机制(如设备型号、语言设置),第二阶段的初始化步骤包括:
-
解析内核启动参数:
-
process_kernel_dt():从设备树(Device Tree)读取硬件相关配置(如分区挂载点),设置ro.boot开头的属性(如ro.boot.vendor_id)。 -
process_kernel_cmdline():解析内核命令行参数(如androidboot.hardware=ranchu),转换为系统属性。- 示例:命令行参数
androidboot.storagemedia=emmc会生成ro.boot.storagemedia=emmc。
- 示例:命令行参数
-
-
导出内核属性:
c
export_kernel_boot_props();- 将内核相关属性(如序列号)同步到用户空间可访问的属性(如
ro.serialno来自ro.boot.serialno)。
- 将内核相关属性(如序列号)同步到用户空间可访问的属性(如
-
加载默认属性文件:
c
property_load_boot_defaults(load_debug_prop);- 读取
/system/etc/prop.default、/system/build.prop等文件,设置系统默认属性(如ro.product.model)。
- 读取
4. SELinux 二次配置:确保安全上下文生效
-
日志重定向:再次调用
SelinuxSetupKernelLogging(),确保第二阶段的 SELinux 日志仍写入内核缓冲区。 -
安全上下文校验:
c
SelinuxRestoreContext();- 遍历关键文件(如
/system/bin下的可执行文件),通过restorecon命令应用默认安全标签,确保文件访问权限符合 SELinux 策略。
- 遍历关键文件(如
5. 进程监控与服务启动
-
初始化 epoll 事件监听:
c
Epoll epoll; InstallSignalFdHandler(&epoll);- 使用 Linux 的 epoll 机制监控子进程退出信号(SIGCHLD),当子进程(如 Zygote)崩溃时,Init 可及时回收资源并重启服务。
-
启动属性服务(Property Service) :
c
StartPropertyService(&epoll);- 属性服务是 Android 系统的「全局配置中心」,允许进程通过
property_get/property_set接口读写系统属性,支持跨进程通信。
- 属性服务是 Android 系统的「全局配置中心」,允许进程通过
-
处理分区挂载与清理:
- 卸载临时挂载点
/debug_ramdisk。 - 挂载厂商覆盖分区(
/system/vendor_overlay),确保不同设备的定制化配置生效。
- 卸载临时挂载点
三、关键知识点总结
-
属性系统的核心作用:
- 系统属性是 Android 的「全局变量」,贯穿启动流程(如
ro.boot系列属性决定设备型号、分区布局)。 - 示例:
ro.boot.selinux=enforcing控制 SELinux 运行模式,ro.product.name决定系统显示名称。
- 系统属性是 Android 的「全局变量」,贯穿启动流程(如
-
进程优先级与监控:
- Init 通过
oom_score_adj确保自身不被杀死,通过 epoll 监听子进程状态,实现「守护进程」的职责(如重启崩溃的 Zygote)。
- Init 通过
-
安全机制的分层实现:
- 第一阶段完成 SELinux 策略加载,第二阶段校验文件安全上下文,确保用户空间服务在严格的安全域中运行。
-
阶段切换的设计思想:
- 第一阶段:「最小化环境搭建」(挂载文件系统、基础安全)。
- 第二阶段:「功能完善与服务启动」(属性初始化、进程监控、服务配置)。
- 通过分阶段解耦,降低启动流程的复杂度,便于问题定位(如属性错误可直接追溯到第二阶段)。
四、类比说明
Init 进程的第二阶段类似「操作系统的初始化向导」:
-
设置优先级:如同给向导最高权限,确保其能完成所有配置步骤。
-
属性系统:类似向导中的「配置表单」,填写设备型号、语言等信息,供后续应用读取。
-
SELinux 校验:类似向导中的「安全检查」,确保所有配置符合安全规范(如禁止应用访问敏感目录)。
-
启动属性服务:如同启动「全局配置数据库」,允许所有应用查询和修改系统参数。
通过这一阶段,Android 系统从「内核控制的裸机环境」过渡到「用户空间主导的可配置环境」,为最终启动桌面(Launcher)和应用程序奠定基础。