Init 进程启动分析五

393 阅读4分钟

Android 系统中 Init 进程解析 init.rc 文件的完整流程,揭示系统服务启动的核心机制:

一、解析准备:构建解析器与加载配置文件

在 Init 进程的第二阶段(SecondStageMain),系统会创建专门的解析器来处理 init.rc 配置。

1. 创建解析器(Parser)

  • 作用:将文本格式的 init.rc 转换为可执行的内部对象(Action 和 Service)。

  • 核心组件

    • ServiceParser:解析 service 块,生成 Service 对象(记录服务名、路径、权限等)。
    • ActionParser:解析 on 块,生成 Action 对象(记录触发条件和执行命令)。
    • ImportParser:处理 import 命令,动态加载其他 .rc 文件(如 init.zygote.rc)。

2. 加载 rc 文件的顺序

系统按以下优先级加载配置文件(前一个文件的配置会被后一个覆盖):

  1. /init.rc:核心配置,定义系统最基础的服务和动作(如 servicemanagerzygote)。

  2. /system/etc/init/ :系统分区的扩展配置(如硬件相关服务)。

  3. /product/etc/init/ :厂商定制分区的配置(如特定型号设备的服务)。

  4. /vendor/etc/init/ :供应商分区的配置(如高通、联发科的私有服务)。

  • 动态加载:若内核参数指定 androidboot.init_rc=xxx,则优先加载指定文件。

二、解析过程:从文本到对象的转换

1. 解析 service 块:生成 Service 对象

示例配置

ini

service zygote /system/bin/app_process64 -Xzygote --zygote --start-system-server
    class core
    user root
    group root readproc
    socket zygote stream 660 root system

解析结果

  • Service 对象属性

    • name_ = "zygote"
    • classnames_ = {"core"}(属于 core 服务类别)
    • user_ = "root"group_ = "root readproc"(运行权限)
    • socket_ = "/dev/socket/zygote"(通信套接字)

2. 解析 on 块:生成 Action 对象

示例配置

ini

on boot
    class_start core  # 启动所有 core 类服务
    setprop sys.boot_completed 1  # 设置系统属性

解析结果

  • Action 对象属性

    • event_trigger_ = "boot"(触发条件为系统启动)
    • commands_ 包含两个命令:class_start core 和 setprop sys.boot_completed 1

三、执行逻辑:事件触发与命令调度

1. 事件队列与动作执行

  • 事件类型

    • 系统事件:如 early-init(初始化早期)、init(初始化完成)、boot(系统启动完成)。
    • 属性事件:如 on property:sys.boot_completed=1(属性值变化时触发)。
  • 执行流程

    1. 入队事件:通过 am.QueueEventTrigger("init") 将事件加入队列。
    2. 匹配动作ActionManager 遍历所有 Action,找到触发条件匹配的 Action(如 on init 对应的 Action)。
    3. 执行命令:按顺序执行 Action 中的每个命令(如先执行 sysclktz 0,再执行 symlink /system/etc /etc)。

2. 服务启动策略

  • 按类别启动:通过 class_start core 批量启动同一类别(如 core)的所有服务。
  • 延迟启动:标记为 disabled 的服务(如 adbd)需手动通过 start adbd 启动。
  • 崩溃重启:未标记 oneshot 的服务崩溃后自动重启;标记 critical 的服务若频繁崩溃(如 4 次 / 4 分钟),系统重启到 Bootloader。

四、关键数据结构与内存管理

1. ActionManager:管理动作执行

  • 核心成员

    • actions_:存储所有解析出的 Action 对象。
    • event_queue_:待处理的事件队列(如 early-initboot)。
  • 执行优化

    • 每次调用 ExecuteOneCommand() 仅执行一个命令,避免长命令阻塞启动流程。
    • 超过 50ms 的命令会被记录警告,便于性能调优。

2. ServiceList:管理服务生命周期

  • 核心成员

    • services_:存储所有解析出的 Service 对象。
    • delayed_service_names_:延迟启动的服务列表(如依赖其他服务的服务)。
  • 状态监控

    • 记录服务的启动时间、崩溃次数、CPU 优先级(oom_score_adj)等,用于资源调度和故障恢复。

五、典型启动流程示例

以 zygote 服务为例,看其从配置到启动的完整路径:

  1. 解析阶段

    • init.rc 中的 service zygote ... 被解析为 Service 对象,加入 ServiceList
  2. 事件触发

    • 当 ActionManager 处理 boot 事件时,执行 class_start core 命令,触发 zygote 启动。
  3. 执行启动

    • Init 进程通过 fork() 创建 zygote 子进程,子进程加载 Java 运行时(ART)并监听应用启动请求。

六、总结:init.rc 如何驱动系统启动

init.rc 是 Android 系统启动的「剧本」,通过 解析 - 调度 - 执行 三部曲实现:

  1. 解析:将文本配置转换为 Action 和 Service 对象,建立系统服务的元数据模型。

  2. 调度:通过事件队列(event_queue_)和动作管理器(ActionManager)按顺序触发初始化操作。

  3. 执行:启动服务、设置属性、挂载分区等具体操作,最终完成从内核到用户空间的过渡。

理解这一流程,不仅能深入掌握 Android 启动机制,还能在定制系统时精准修改服务配置(如添加自定义服务、调整启动顺序),是系统开发与调试的核心基础。