Android 系统启动流程
Android 系统启动流程分析。
Android 启动流程
通用的 Linux 系统流程如下图(图片来自《Androi内核剖析》):
Android 系统启动流程如下图(图片参考自 Android系统启动流程 | 风中老狼的博客):
关键代码
- Linux 内核入口
/init/main.c
- init 进程,这是第一个用户进程
- 命令:
/sbin/init
- 代码:
/system/core/init/init.cpp
- 配置:
- 主配置 -
/system/etc/init/hw/init.rc
- 其他配置 -
/{system,system_ext,vendor,odm,product}/etc/init/
目录下
- 主配置 -
- 命令:
- zygote 进程,这是第一个 Java 进程,用于孵化后续的应用进程
- 命令:
/system/bin/app_process
- 代码:
/frameworks/base/cmds/app_process/App_main.cpp
/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
- 命令:
- SystemServer 进程,对外提供 AmS 和 WmS 等 Manager
- 命令: -
/system/bin/app_process
- 代码:
/frameworks/base/core/java/android/app/ActivityThread.java
/frameworks/base/services/java/com/android/server/SystemServer.java
- 命令: -
- ServiceManager 进程,管理 Service
- 命令:
/system/bin/servicemanager
- 代码:-
/frameworks/native/cmds/servicemanager.ServiceManager.cpp
- 命令:
代码分析
Linux 内核
内核的入口是 /init/main.c kernel_init() ,最终通过 run_init_process()
启动 init 进程。
1 | noinline void __ref rest_init(void) |
init 进程
按 init README.md的描述,init 进程分3个不同的执行阶段:
init
命令的入口是 init/main.cpp main():
1 | int main(int argc, char** argv) { |
3个不同阶段对应的代码如下。这里略去了具体的细节,但从执行流程上可以看到 first stage 和 selinux setup 两个阶段再次执行了 init 命令。
1 | int FirstStageMain(int argc, char** argv) { |
1 | int SetupSelinux(char** argv) { |
1 | int SecondStageMain(int argc, char** argv) { |
Zygote 进程
1 | service zygote /system/bin/app_process64 -Xzygote |
1 | int main(int argc, char* const argv[]) |
- core/java/com/android/internal/os/ZygoteInit.java - platform/frameworks/base - Git at Google
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
public static void main(String[] argv) {
ZygoteServer zygoteServer = null;
...
Runnable caller;
try {
boolean startSystemServer = false;
String zygoteSocketName = "zygote";
...
boolean enableLazyPreload = false;
for (int i = 1; i < argv.length; i++) {
if ("start-system-server".equals(argv[i])) {
startSystemServer = true;
} else if ("--enable-lazy-preload".equals(argv[i])) {
enableLazyPreload = true;
}
}
if (!enableLazyPreload) {
...
preload(bootTimingsTraceLog);
...
}
zygoteServer = new ZygoteServer(isPrimaryZygote);
if (startSystemServer) {
Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);
// {@code r == null} in the parent (zygote) process, and {@code r != null} in the
// child (system_server) process.
if (r != null) {
r.run();
return;
}
}
...
// The select loop returns early in the child process after a fork and
// loops forever in the zygote.
caller = zygoteServer.runSelectLoop(abiList);
...
}
// We're in the child process and have exited the select loop. Proceed to execute the
// command.
if (caller != null) {
caller.run();
}
}
FAQ
servicemanager 和 zygote 进程的先后顺序
看下图可知,
- init 阶段启动 servicemanager 进程
- late-init 阶段启动 zygote 进程
所以 servicemanager 进程先于 zygote 进程启动
servicemanager 进程先于 zygote 进程启动的原因
(以下内容来自 GPT-4o 对问题 “servicemanager 进程 和 zygote 进程,哪个先被启动” 的回答)
在 Android 系统中,servicemanager
进程会在 zygote
进程之前被启动。这是因为 servicemanager
进程是 Android 系统中非常重要的一部分,负责管理系统服务的注册和调用,包括跨进程通信和系统服务的绑定。
具体的启动顺序如下:
servicemanager
进程启动:在 Android 系统启动过程中,首先会启动servicemanager
进程。servicemanager
是 Android 中的 Binder IPC(Inter-process Communication,进程间通信)机制的守护进程,用于管理系统服务的注册和调用。zygote
进程启动:接着,zygote
进程会被启动。zygote
进程作为孵化器进程,负责预加载常用的 Java 类和系统资源,以加速应用程序的启动。
通过这种启动顺序,servicemanager
进程首先被启动可以确保系统服务的注册和通信机制在系统启动之初就已经准备就绪,为后续应用程序进程的启动提供了基础。而 zygote
进程的启动则利用了 servicemanager
进程提供的系统服务注册功能,从而更高效地加载应用程序。
因此,servicemanager
进程在 Android 系统启动时是比 zygote
进程更早被启动的重要组件之一。
Android 的 init 命令有什么不同
传统 Linux 发行版中的 /sbin/init 通常是链接到 SystemV init 或 systemd 系统,这些系统是为通用计算环境设计的,提供了更复杂的服务管理和系统初始化特性
Android 的 init 是专门为移动设备环境设计的,它主要是挂载文件系统、加载 SELinux(可选)、解析并执行 init.rc
脚本并重启某些服务