Android init 进程的启动过程

init 进程是 Android 系统中用户空间的第一个进程,进程号为 1。作为第一个进程,它被赋予了很多重要的职责,比如创建 Zygote 进程和属性服务等。

init 进程由多个源文件共同组成,这些文件位于源码目录 system/core/init 中。

Android 系统启动的前几步

  1. 当电源接通时。引导芯片代码从预定义的地方(硬编码在 ROM)开始执行。加载引导程序 BootLoader 到 (内存)RAM 中,然后执行。

  2. BootLoader 是在 Android 系统开始运行前的一个小程序(它不是 Android 的一部分)。BootLoader 是制造商放置锁定和限制的地方。BootLoader 分两个阶段执行。 在第一阶段,它检测外部 RAM 并加载程序。在第二阶段,为内核启动做准备,引导加载程序设置网络,内存等

  3. Android 内核的启动方式与 Linux 内核类似。随着内核的启动,开始设置缓存,受保护的内存,调度和加载驱动程序。当内核完成系统设置时,它会在系统文件中查找 init 文件。

  4. init 进程启动

  • 创建和挂载启动所需的文件目录
  • 初始化和启动属性服务
  • 解析 init.rc 脚本,并启动 Zygote 进程

init 进程的入口

在 Android 内核加载完成后,它会执行 init 进程的入口函数 mainmain 函数中会解析 init.rc 配置文件到 Action Service 对象中,然后执行 Actions 中的命令。

init.rc 是按照 Android Init Language 语法编写的脚本。

解析 Service Section 流程

在 init 进程在执行 main 方法时,会解析执行 /init.rc 脚本,init.rc 脚本中会 import 与 zygote 相关的 init.${ro.zygote}.rc 脚本:

ro.zygote 是一个编译期指定的属性值,可以为 zygote32、zygote64、zygote32_64、zygote64_32

1
2
3
4
5
6
import /init.environ.rc
import /init.usb.rc
import /init.${ro.hardware}.rc
import /vendor/etc/init/hw/init.${ro.hardware}.rc
import /init.usb.configfs.rc
import /init.${ro.zygote}.rc

由于 zygote 属于 Service,所以举例解析 Service 的流程图,解析 Action 的流程类似

启动 Zygote

待配置文件解析完成之后,就会开始依次支持 Actions 里的命令,在 init.rc 中能看到有如下配置:

init.rc

1
2
3
on nonencrypted
class_start main // 执行 class_start 命令,参数为 main
class_start late_start

表示当 nonencrypted 事件发生时,就执行下面定义的命令 class_start main 等。

system/core/init/builtins.cpp 中每个命令对应的解析函数关系

1
2
3
4
5
6
7
8
9
10
11
12
const BuiltinFunctionMap::Map& BuiltinFunctionMap::map() const {
constexpr std::size_t kMax = std::numeric_limits<std::size_t>::max();
static const Map builtin_functions = {
...
{"class_reset", {1, 1, do_class_reset}},
{"class_restart", {1, 1, do_class_restart}},
{"class_start", {1, 1, do_class_start}},
...
{"write", {2, 2, do_write}},
};
return builtin_functions;
}

所以 class_start main 会执行 do_class_start 方法,并传递参数 main:

1
2
3
4
5
static int do_class_start(const std::vector<std::string>& args) {
ServiceManager::GetInstance().ForEachServiceInClass(args[1], [] (Service* s) { s->StartIfNotDisabled(); });
// 循环执行 class name 匹配 args[1](这里是main) 的 Service 的 StartIfNotDisabled
return 0;
}
1
2
3
4
5
6
7
8
bool Service::StartIfNotDisabled() {
if (!(flags_ & SVC_DISABLED)) {
return Start();
} else {
flags_ |= SVC_DISABLED_START;
}
return true;
}

init.zygote64.rc 中配置的 zygote 服务的 class name 恰恰就是 main

1
2
3
4
5
6
7
8
service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server
class main // 指定服务的类名。 同一个类名中的所有服务可以一起启动或停止。 如果未通过 class 选项指定服务,则服务在类“default”中
priority -20 // 调度服务进程的优先级。 该值必须在 [-20,19] 的范围内。默认优先级为 0
user root
group root readproc
socket zygote stream 660 root system // 创建一个名为 /dev/socket/name 的 UNIX 域 socket,并将其 fd 传递给已启动的进程
...
writepid /dev/cpuset/foreground/tasks // 当 forks 时,将 child 进程的 pid 写入给定的文件

所以这里会执行在解析配置阶段构造的对应 zygote service 配置的 Service 对象的 Start() 方法。

至此,通过 JNI 就从 cpp 运行环境切换到了 java 环境下运行, ZygoteInit 在子进程中开始执行 main 方法

ZygoteInit.java#main

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
47
48
49
50
51
52
53
54
55
public static void main(String argv[]) {
ZygoteServer zygoteServer = new ZygoteServer();
//...
final Runnable caller;
try {
//...

boolean startSystemServer = false;
String socketName = "zygote";
String abiList = null;
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;
} else if (argv[i].startsWith(ABI_LIST_ARG)) {
abiList = argv[i].substring(ABI_LIST_ARG.length());
} else if (argv[i].startsWith(SOCKET_NAME_ARG)) {
socketName = argv[i].substring(SOCKET_NAME_ARG.length());
} else {
throw new RuntimeException("Unknown command line argument: " + argv[i]);
}
}

if (abiList == null) {
throw new RuntimeException("No ABI list supplied.");
}

// 创建一个 LocalServerSocket, 用来接收其他服务的请求
zygoteServer.registerServerSocket(socketName);
//...
if (startSystemServer) {
// 通过 fork 一个子进程来启动 System Server
Runnable r = forkSystemServer(abiList, socketName, zygoteServer);
// {@code r == null } 说明还是运行在父(zygote)进程
// {@code r != null } 说明运行在子(system_server)进程
if (r != null) {
r.run();
// 这里的 return 是让子(system_server)进程不执行下面的代码, zygote 进程还是继续向下运行
return;
}
}

caller = zygoteServer.runSelectLoop(abiList);
} catch (Throwable ex) {
throw ex;
} finally {
zygoteServer.closeServerSocket();
}

if (caller != null) {
caller.run();
}
}
赏杯咖啡 🍵 Donate