Android系统开发进阶-init 进程启动流程
Android系统开发进阶-init 进程启动流程
上一篇文章我们详细解析了 init.rc 文件的语法规范。同学们可以对照着去看看 Android/system/core/rootdir/init.rc 这个文件。我们会发现里面有很多 event trigger, 比如 on boot
, on fs
等,然后系统的各种核心服务,基本上都是在这些 event trigger 里面启动的。以前一直搞不明白这些 event trigger 的先后执行顺序。这次把源码看了一遍过,终于搞明白了。本文不会从源码的角度去分析 init 的启动流程,只是把自己看过源码之后的理解, 整理成一张思维导图,相信同学们看过这张图之后应该能大概明白 init 都干了哪些活。这些活的先后顺序,这就足够了。
init 启动流程概要:
从上图来看, init 的初始化可以分为三个阶段:
- FirstStageMain
这个阶段的工作主要是挂载一些虚拟文件系统,还有挂载两个系统最核心的分区 system, vendor。
这两步都是为了后续的工作做准备。比如设置 selinux 需要从 system, vendor 分区中读取 sepolicy。 SecondStageMain 需要从 system, vendor 分区中读取 property 信息,需要启动系统核心服务。 - SetupSelinux
设置 Selinux 安全机制。 - SecondStageMain
启动 property 服务(从这里可以知道 property 服务是运行在 init 进程里面的),然后加载各分区下的 .rc 文件。然后把各种事件加入到事件队列。最后进入事件循环,按队列方式(先进先出)处理事件队列中的事件。
从上面的流程来看,其实 init 把大部分的初始化工作都放到 init.rc 中, 这样可以更灵活的适配各种平台的定制需求。
需要提一下的是各阶段的启动方式,第一阶段的启动是由 kernel 启动的,这里不讨论,第二,三阶段的启动比较有意思,都是通过 exec 来启动的:
1
|
const char* path = "/system/bin/init";
|
1
|
const char* path = "/system/bin/init";
|
我也不知道为什么要通过 execv 启动一个新进程替换旧进程的方式来切换各阶段呢?这样相比直接一个函数调用来说有什么好处呢?知道的同学麻烦指导一下哈。
单独把 secondStage 部分的流程拎出来扩展:
这张图主要是想表现一下各事件触发器的触发时序,各服务的启动时序。整理如下:
0. 初始化 biner 驱动相关
-
early-init 事件
启动了 ueventd, apexd-bootstrap 服务 -
init 事件
1
2
3
4
5
6
7
8
9
10
11on init
# 创建各种系统运行所需的目录,更改各种目录的权限
mkdir /mnt/media_rw 0750 root media_rw
mkdir /mnt/user 0755 root root
# Start logd before any other services run to ensure we capture all of their logs.
start logd
# Start essential services.
start servicemanager
start hwservicemanager
start vndservicemanager -
late-init 事件
把一堆的事件按顺序加入事件队列1
2
3
4
5
6
7
8
9
10
11on late-init
trigger early-fs
trigger fs
trigger post-fs
trigger late-fs
trigger post-fs-data
trigger load_persist_props_action
trigger zygote-start
trigger firmware_mounts_complete
trigger early-boot
trigger boot -
early-fs 事件
启动 vold 服务,负责外接磁盘的挂载。 -
fs 事件
Action 定义在 vendor/etc/init/init.ranchu.rc 中, 只有一个动作,根据 fstab 挂载所有分区。1
mount_all /vendor/etc/fstab.ranchu
在挂完文件系统后,代码中会把 nonencrypted 事件加入到事件队列。
-
post-fs 事件
重新挂载 / 根分区为只读分区,创建各种系统目录。 -
late-fs 事件
启动 early_hal 类型的所有服务,当然被 disable 的除外。 -
post-fs-data 事件
启动 bootchart, apexd, 等待 apexd 服务完成 -
load_persist_props_action 事件
加载 /data 分区下的 persist property -
zygote-start 事件
Android 世界的鼻祖在这里启动了 -
firmware_mounts_complete 事件
这个不知道干啥用的了 -
early-boot 事件
目前没有使用 -
boot 事件
启动 hal, core 类型的所有服务,当然被 disable 的除外。 -
nonencrypted 事件
启动 main 类型的所有服务,当然被 disable 的除外。
以上,我们可以知道各种服务的启动顺序了:
最先启动的是 logd, 和三个 servicemanager 服务。
接下来按这个顺序来启动各种类型的服务:
early_hal –> hal –> core –> main
- 版权声明: 本博客所有文章除特别声明外,均采用 CC BY 4.0 CN协议 许可协议。转载请注明出处!
每一个不曾起舞的日子,都是对生命的辜负。
But it is the same with man as with the tree. The more he seeks to rise into the height and light, the more vigorously do his roots struggle earthward, downward, into the dark, the deep - into evil.
其实人跟树是一样的,越是向往高处的阳光,它的根就越要伸向黑暗的地底。----尼采