“进程鼻祖” -- Zygote

核心源码(Android_10.0)

关键类 路径
init.rc system/core/rootdir/init.rc
init.cpp system/core/init/init.cpp
init.zygote64.rc system/core/rootdir/init.zygote64.rc
builtins.cpp system/core/init/builtins.cpp
service.cpp system/core/init/service.cpp
app_main.cpp frameworks/base/cmds/app_process/app_main.cpp
AndroidRuntime.cpp frameworks/base/core/jni/AndroidRuntime.cpp
JniInvocation.cpp libnativehelper/JniInvocation.cpp
LocalServerSocket.cpp frameworks/base/core/java/android/net/LocalServerSocket.java
ZygoteInit.java frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
ZygoteServer.java frameworks/base/core/java/com/android/internal/os/ZygoteServer.java

# Zygote简介

在 Android 系统中,JavaVM(Java虚拟机)应用程序进程以及运行系统关键服务的 SystemServer 进程都是由 Zygote 来创建的,我们也将它称为 孵化器。它通过 fock (复制进程)的形式来创建 “应用程序进程” 和 “SystemServer 进程”,由于 Zygote 进程在启动时会创建 JavaVM,因此通过 fock 而创建的 “应用程序进程” 和 “SystemServer 进程” 可以在内部获取一个 JavaVM 的实例拷贝

一、Zygote

1.1 触发

在前面分析 init 进程 时,我们知道 init 进程启动后,会解析 init.rc 文件,然后创建和加载 service 字段 指定的进程。zygote 进程就是以这种方式被 init 进程加载的。

system/core/rootdir/init.rc 中,可以看到:

1
2
3
4
5
6
7
8
// system/core/rootdir/init.rc

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 // ${ro.zygote} 由厂商定义,与平台相关

1.2 init.xx.rc

在不同的平台(32、64 及 64_32)上,init.rc 将包含不同的 zygote.rc 文件。

system/core/rootdir 目录下:

init.zygote32_64.rcinit.zyote64.rcinit.zyote32.rcinit.zygote64_32.rc 四个文件。

init.zygote32.rc

zygote 进程对应的执行程序是 app_process (纯 32bit 模式)

init.zygote64.rc

zygote 进程对应的执行程序是 app_process64 (纯 64bit 模式)

init.zygote32_64.rc

启动两个 zygote 进程 (zygote 和 zygote_secondary),对应的执行程序分别是 app_process32 (主模式)、app_process64

init.zygote64_32.rc

启动两个 zygote 进程 (zygote 和 zygote_secondary),对应的执行程序分别是 app_process64 (主模式)、app_process32

为什么要定义这么多种情况?

这主要是因为 Android 5.0 以后开始支持 64 位程序,为了兼容 32 位和 64 位才这样定义。不同的 zygote.rc 内容大致相同,主要区别体现在启动的是 32 位,还是 64 位的进程。init.zygote32_64.rcinit.zygote64_32.rc 会启动两个进程,且存在主次之分。

这里拿 64 位处理器为例,init.zygote64_32.rc 的代码如下所示:

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
/* 
* 进程名称是 zygote
* 运行的二进制文件在 /system/bin/app_process64
* 启动参数是 -Xzygote /system/bin --zygote --start-system-server --socket-name=zygote
*/
service zygote /system/bin/app_process64
-Xzygote /system/bin --zygote --start-system-server --socket-name=zygote
class main
priority -20
user root
group root readproc reserved_disk
socket zygote stream 660 root system // 创建一个 socket,名字叫 zygote
socket usap_pool_primary stream 660 root system
onrestart write /sys/android_power/request_state wake // onrestart 指当进程重启时执行后面的命令
onrestart write /sys/power/state on
onrestart restart audioserver
onrestart restart cameraserver
onrestart restart media
onrestart restart netd
onrestart restart wificond
writepid /dev/cpuset/foreground/tasks // 创建子进程时,向 /dev/cpuset/foreground/tasks 写入 pid

// 另一个 service:zygote_secondary
service zygote_secondary /system/bin/app_process32
-Xzygote /system/bin --zygote --socket-name=zygote_secondary --enable-lazy-preload
class main
priority -20
user root
group root readproc reserved_disk
socket zygote_secondary stream 660 root system
socket usap_pool_secondary stream 660 root system
onrestart restart zygote
writepid /dev/cpuset/foreground/tasks

1.3 start zygote

既然定义了此 service 用于启动 Zygote,那么是在什么地方启动的呢?在探讨 init 的时候,我们分析过:init 进程启动的最后,会处理 late-init 事件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// system/core/init/init.cpp

int SecondStageMain(int argc, char** argv) {

// Don't mount filesystems or start core system services in charger mode.
std::string bootmode = GetProperty("ro.bootmode", "");
if (bootmode == "charger") {
am.QueueEventTrigger("charger");
} else {
am.QueueEventTrigger("late-init");
}

return 0;

}

对应于 init.rc 配置文件中,我们找到如下代码:

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
// system/core/rootdir/init.rc

# Mount filesystems and start core system services.
on late-init
... ...

# Now we can start zygote for devices with file based encryption
trigger zygote-start // 触发了 zygote-start 事件后,就会启动 zygote 进程
... ...

# It is recommended to put unnecessary data/ initialization from post-fs-data
# to start-zygote in device's init.rc to unblock zygote start.
on zygote-start && property:ro.crypto.state=unencrypted
# A/B update verifier that marks a successful boot.
exec_start update_verifier_nonencrypted
start netd // start 对应的映射关系定义于 /system/core/init/builtins.cpp 中
start zygote // 调用 start 对应的处理函数,启动名为 zygote 的服务(传入前文 init.zygote.rc 中定义的参数)
start zygote_secondary

on zygote-start && property:ro.crypto.state=unsupported
# A/B update verifier that marks a successful boot.
exec_start update_verifier_nonencrypted
start netd
start zygote
start zygote_secondary

on zygote-start && property:ro.crypto.state=encrypted && property:ro.crypto.type=file
# A/B update verifier that marks a successful boot.
exec_start update_verifier_nonencrypted
start netd
start zygote
start zygote_secondary

start 命令有一个对应的执行函数 do_start ,定义在 /system/core/init/builtins.cpp 中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// system/core/init/builtins.cpp

// Builtin-function-map start
const BuiltinFunctionMap::Map& BuiltinFunctionMap::map() const {
constexpr std::size_t kMax = std::numeric_limits<std::size_t>::max();
// clang-format off
static const Map builtin_functions = {
... ...

{"start", {1, 1, {false, do_start}}},

... ...
};
// clang-format on
return builtin_functions;
}

我们看下 do_start()

1
2
3
4
5
6
7
8
9
10
11
12
// system/core/init/builtins.cpp

static Result<Success> do_start(const BuiltinArguments& args) {
// 找到 zygote service 对应信息
Service* svc = ServiceList::GetInstance().FindService(args[1]);
if (!svc) return Error() << "service " << args[1] << " not found";
// 启动对应的进程
if (auto result = svc->Start(); !result) {
return Error() << "Could not start service: " << result.error();
}
return Success();
}

do_start 首先是通过 FindService 去 service 数组中遍历,根据名字匹配出对应的 service,然后调用 service 的 Start 函数。

最后,我们来看看 service.cpp 中定义 Start 函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// system/core/init/service.cpp

Result<Success> Service::Start() {
... ...

pid_t pid = -1;
if (namespace_flags_) {
pid = clone(nullptr, nullptr, namespace_flags_ | SIGCHLD, nullptr);
} else {
pid = fork(); // 从 init 进程中,fork 出 zygote 进程
}

... ...
}

Start 函数主要是 fork 出一个新进程,然后执行 service 对应的二进制文件,并将参数传递进去,下面我们以 init.zygote64.rc 为例进行分析。

二、app_process

init.zygote64.rc 启动文件的地址为 /system/bin/app_process64

init.zygote64.rc

app_process64 对应的代码定义在 frameworks/base/cmds/app_process目录下。

我们来看看对应的 Android.mk

1
2
3
4
5
6
7
8
9
10
11
12
// frameworks/base/cmds/app_process

LOCAL_PATH:= $(call my-dir)
... ...
app_process_src_files := \
app_main.cpp \
... ...
LOCAL_MODULE:= app_process
LOCAL_MULTILIB := both
LOCAL_MODULE_STEM_32 := app_process32
LOCAL_MODULE_STEM_64 := app_process64
... ...

其实不管是 app_process、app_process32 还是 app_process64,对应的源文件都是 app_main.cpp

接下来我们就看看 app_process 对应的 main 函数,该函数定义于 app_main.cpp 中。

2.1 app_main

在 app_main.cpp 的 main 函数中,主要做的事情就是参数解析。这个函数有 两种 启动模式:

zygote 模式,也就是初始化 zygote 进程,传递的参数有 “–start-system-server –socket-name=zygote”,前者表示启动 SystemServer,后者指定 socket 的名称(Zygote64_32)。
application 模式,也就是启动普通应用程序,传递的参数有 “class 名字”以及 “class 带的参数”。

两者最终都是调用 AppRuntime 对象start 函数,加载 ZygoteInitRuntimeInit 两个 Java 类,并将之前整理的参数传入进去。

我们这里以 ZygoteInit 为例,讲解其加载流程,接下来正式开始 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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
// frameworks/base/cmds/app_process/app_main.cpp

int main(int argc, char* const argv[])
{
// 将参数 argv 放到 argv_String 字符串中,然后打印出来
// 之前 start zygote 传入的参数是 -Xzygote /system/bin --zygote --start-system-server
if (!LOG_NDEBUG) {
String8 argv_String;
for (int i = 0; i < argc; ++i) {
argv_String.append("\"");
argv_String.append(argv[i]);
argv_String.append("\" ");
}
ALOGV("app_process main with argv: %s", argv_String.string());
}

// AppRuntime 定义于 app_main.cpp 中,继承自 AndroidRuntime
// 就是对 Android 运行环境的一种抽象,类似于 java 虚拟机对 Java 程序的作用
AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
argc--;
argv++;

// 这两个参数是 Java 程序需要依赖的 Jar 包,相当于 import
const char* spaced_commands[] = { "-cp", "-classpath" };
bool known_command = false;

int i;
// 找到解析参数的起点
for (i = 0; i < argc; i++) {
// 将 spaced_commands 中的参数额外加入 VM
if (known_command == true) {
runtime.addOption(strdup(argv[i]));
ALOGV("app_process main add known option '%s'", argv[i]);
known_command = false;
continue;
}

for (int j = 0;
j < static_cast<int>(sizeof(spaced_commands) / sizeof(spaced_commands[0]));
++j) {
// 比较参数是否是 spaced_commands 中的参数
if (strcmp(argv[i], spaced_commands[j]) == 0) {
known_command = true;
ALOGV("app_process main found known command '%s'", argv[i]);
}
}

// 如果参数第一个字符是'-',直接跳出循环,之前传入的第一个参数是 -Xzygote,所以执行到这儿就跳出了
if (argv[i][0] != '-') {
break;
}
if (argv[i][1] == '-' && argv[i][2] == 0) {
++i; // Skip --.
break;
}

runtime.addOption(strdup(argv[i]));
ALOGV("app_process main add option '%s'", argv[i]);
}

// 从这里其实可以看出,通过 app_main 可以启动 zygote、system-server 及普通 apk 进程
bool zygote = false;
bool startSystemServer = false;
bool application = false;
String8 niceName; // app_process 的名称改为 zygote
String8 className; // 启动 apk 进程时,对应的类名

++i;
// 跳过一个参数,之前跳过了 -Xzygote,这里继续跳过 /system/bin ,也就是所谓的 "parent dir"
while (i < argc) { // 开始解析输入参数
const char* arg = argv[i++];
if (strcmp(arg, "--zygote") == 0) { // 表示是 zygote 启动模式
zygote = true;
niceName = ZYGOTE_NICE_NAME; // 这个值根据平台可能是 zygote64 或 zygote
} else if (strcmp(arg, "--start-system-server") == 0) {
startSystemServer = true; // init.zygote.rc 中定义,启动 zygote 后会启动 system-server
} else if (strcmp(arg, "--application") == 0) {
application = true; // 表示是 application 启动模式,也就是普通应用程序
} else if (strncmp(arg, "--nice-name=", 12) == 0) {
niceName.setTo(arg + 12); // 进程别名,可以自己指定进程名
} else if (strncmp(arg, "--", 2) != 0) {
className.setTo(arg); // 与 --application 配置,启动指定的类,application 启动的 class
break;
} else {
--i;
break;
}
}

// 准备参数
Vector<String8> args;
if (!className.isEmpty()) { // className 不为空,说明是 application 启动模式
args.add(application ? String8("application") : String8("tool"));
runtime.setClassNameAndArgs(className, argc - i, argv + i);
... ...
} else { // zygote 启动模式
// We're in zygote mode.
maybeCreateDalvikCache(); // 创建 Dalvik 的缓存目录并定义权限

if (startSystemServer) { // 增加 start-system-server 参数
args.add(String8("start-system-server"));
}

char prop[PROP_VALUE_MAX]; // 获取平台对应的 abi 信息
if (property_get(ABI_LIST_PROPERTY, prop, NULL) == 0) {
LOG_ALWAYS_FATAL("app_process: Unable to determine ABI list from property %s.",
ABI_LIST_PROPERTY);
return 11;
}

String8 abiFlag("--abi-list="); // 参数需要制定 abi
abiFlag.append(prop);
args.add(abiFlag); // 加入 --abi-list= 参数

for (; i < argc; ++i) {
args.add(String8(argv[i])); // 将剩下的参数加入 args
}
}

if (!niceName.isEmpty()) { // 将 app_process 的进程名,替换为 niceName
runtime.setArgv0(niceName.string(), true /* setProcName */);
}

if (zygote) { // 调用 Runtime 的 start 函数, 启动 ZygoteInit
runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
} else if (className) { // 启动 zygote 没有进入这个分支
// 但这个分支说明,通过配置 init.rc 文件,其实是可以不通过 zygote 来启动一个进程,
// 如果是 application 启动模式,则加载 RuntimeInit。
runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
} else {
// error 情况
fprintf(stderr, "Error: no class name or --zygote supplied.\n");
app_usage();
LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
}
}

Ok,现在我们知道启动 Zygote 是通过 runtime.start 函数,此处的 runtimeAppRuntime

2.2 AndroidRuntime

由于 AppRuntime 继承自 AndroidRuntime,且没有重写 start 方法,因此 zygote 的流程进入到了 AndroidRuntime.cpp

1
2
3
4
5
6
7
8
9
10
11
12
// frameworks/base/cmds/app_process/app_main.cpp

class AppRuntime : public AndroidRuntime
{
public:
AppRuntime(char* argBlockStart, const size_t argBlockLength)
: AndroidRuntime(argBlockStart, argBlockLength)
, mClass(NULL)
{
}
... ...
}

接下来,我们来看看 AndroidRuntime.start 函数的流程。

2.2.1 创建 Java 虚拟机

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// frameworks/base/core/jni/AndroidRuntime.cpp

void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
... ... // 打印一些日志,获取 ANDROID_ROOT 环境变量

/* start the virtual machine */
JniInvocation jni_invocation;
jni_invocation.Init(NULL); // 初始化 JNI,加载 libart.so
JNIEnv* env;

// 创建虚拟机,其中大多数参数由系统属性决定,最终 startVm 利用 JNI_CreateJavaVM 创建出虚拟机
if (startVm(&mJavaVM, &env, zygote) != 0) {
return;
}
// 回调 AppRuntime 的 onVmCreated 函数
// 对于 zygote 进程的启动流程而言,无实际操作,表示虚拟创建完成,但是里面是空实现
onVmCreated(env);
... ...
}

2.2.2 注册 JNI 函数

初始化 JVM 后,接下来就会调用 startReg 函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// frameworks/base/core/jni/AndroidRuntime.cpp

void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
... ...
/* 01. 创建 Java 虚拟机 */
/*
* Register android functions.
*/
if (startReg(env) < 0) { // 注册 JNI 函数
ALOGE("Unable to register all android natives\n");
return;
}
... ...
}

startReg 首先是设置了 Android 创建线程的处理函数,然后创建了一个 200 容量的局部引用作用域,用于确保不会出现 OutOfMemoryException,最后就是调用 register_jni_procs 进行 JNI 注册。

我们跟进源码看下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// frameworks/base/core/jni/AndroidRuntime.cpp

/*static*/ int AndroidRuntime::startReg(JNIEnv* env)
{
// 定义 Android 创建线程的 func:javaCreateThreadEtc,这个函数内部是通过 Linux 的 clone 来创建线程的
androidSetCreateThreadFunc((android_create_thread_fn) javaCreateThreadEtc);

env->PushLocalFrame(200); // 创建一个 200 容量的局部引用作用域,这个局部引用其实就是局部变量

if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) { // 注册 JNI 函数
env->PopLocalFrame(NULL);
return -1;
}

env->PopLocalFrame(NULL); // 释放局部引用作用域

return 0;
}

从上述代码可以看出,startReg 函数中主要是通过 register_jni_procs注册 JNI 函数。其中,gRegJNI 是一个全局数组,该数组的定义如下:

1
2
3
4
5
6
7
8
9
10
// frameworks/base/core/jni/AndroidRuntime.cpp

static const RegJNIRec gRegJNI[] = { // 里面就是一堆函数指针
REG_JNI(register_com_android_internal_os_RuntimeInit),
REG_JNI(register_com_android_internal_os_ZygoteInit_nativeZygoteInit),
REG_JNI(register_android_os_SystemClock),
REG_JNI(register_android_util_EventLog),
REG_JNI(register_android_util_Log),
... ...
};

我们挑一个 register_com_android_internal_os_ZygoteInit_nativeZygoteInit,这实际上是自定义 JNI 函数并进行 动态注册 的标准写法。关于 JNI 的讲解,你可以阅读 【 Android ‘核心机制’ 】篇 – 必须了解的 “JNI” 一文。

内部是调用 JNI 的 RegisterNatives,这样注册后,Java 类 ZygoteInitnative 方法 nativeZygoteInit 就会调用 com_android_internal_os_ZygoteInit_nativeZygoteInit 函数。

1
2
3
4
5
6
7
8
9
10
11
// frameworks/base/core/jni/AndroidRuntime.cpp

int register_com_android_internal_os_ZygoteInit_nativeZygoteInit(JNIEnv* env)
{
const JNINativeMethod methods[] = {
{ "nativeZygoteInit", "()V",
(void*) com_android_internal_os_ZygoteInit_nativeZygoteInit },
};
return jniRegisterNativeMethods(env, "com/android/internal/os/ZygoteInit",
methods, NELEM(methods));
}

REG_JNI 对应的 宏定义RegJNIRec 结构体的定义为:

1
2
3
4
5
6
7
8
9
10
11
12
#ifdef NDEBUG
#define REG_JNI(name) { name }
struct RegJNIRec {
int (*mProc)(JNIEnv*);
};
#else
#define REG_JNI(name) { name, #name }
struct RegJNIRec {
int (*mProc)(JNIEnv*);
const char* mName;
};
#endif

根据宏定义可以看出,宏 REG_JNI 将得到函数名;定义 RegJNIRec 数组时,函数名被赋值给 RegJNIRec 结构体,于是每个函数名被强行转换为函数指针

因此,register_jni_procs参数 就是一个 函数指针数组数组的大小JNIEnv

我们来跟进一下 register_jni_procs 函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// frameworks/base/core/jni/AndroidRuntime.cpp

static int register_jni_procs(const RegJNIRec array[], size_t count, JNIEnv* env)
{
for (size_t i = 0; i < count; i++) {
if (array[i].mProc(env) < 0) { // 调用 mProc
#ifndef NDEBUG
ALOGD("----------!!! %s failed to load\n", array[i].mName);
#endif
return -1;
}
}
return 0;
}

结合前面的分析,容易知道 register_jni_procs 函数,实际上就是调用函数指针(mProc)对应的函数,以进行实际的 JNI 函数注册

2.2.3 反射启动 ZygoteInit

继续分析 AndroidRuntime.cppstart 函数:

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
// frameworks/base/core/jni/AndroidRuntime.cpp

void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
... ...
/* 01. 创建 Java 虚拟机*/
/* 02. 注册 JNI 函数 */
... ...
// 替换 string 为实际路径
// 例如:将 "com.android.internal.os.ZygoteInit" 替换为 "com/android/internal/os/ZygoteInit"
char* slashClassName = toSlashClassName(className != NULL ? className : "");
jclass startClass = env->FindClass(slashClassName); // 找到 class 文件
if (startClass == NULL) {
ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
/* keep going */
} else {
jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
"([Ljava/lang/String;)V"); // 通过反射找到 ZygoteInit 的 main 函数
if (startMeth == NULL) {
ALOGE("JavaVM unable to find main() in '%s'\n", className);
/* keep going */
} else {
env->CallStaticVoidMethod(startClass, startMeth, strArray); // 调用 ZygoteInit 的 main 函数
... ...
}
}
free(slashClassName);

ALOGD("Shutting down VM\n");
if (mJavaVM->DetachCurrentThread() != JNI_OK) // 退出当前线程
ALOGW("Warning: unable to detach main thread\n");
if (mJavaVM->DestroyJavaVM() != 0) // 创建一个线程,该线程会等待所有子线程结束后关闭虚拟机
ALOGW("Warning: VM did not shut down cleanly\n");
}

main 函数最后,将 通过反射调用 ZygoteInit 的 main 函数,至此,zygote 进程正式进入了 java 世界

其实我们仔细想一想,就会觉得 zygote 的整个流程实际上是非常符合实际情况的。

      1、在 Android 中,每个进程都运行在对应的虚拟机上,因此 zygote 首先就负责创建出虚拟机。
      2、然后,为了反射调用 java 代码,必须有对应的 JNI 函数,于是 zygote 进行了 JNI 函数的注册。
      3、当一切准备妥当后,zygote 进程才进入到了 java 世界。

三、ZygoteInit

现在我们跟进 ZygoteInitmain 函数。

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
56
57
58
59
60
61
62
63
64
65
66
67
68
// frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

public class ZygoteInit {
... ...
public static void main(String argv[]) {
// 创建 ZygoteServer 对象
ZygoteServer zygoteServer = new ZygoteServer();

// 调用 native 函数,确保当前没有其它线程在运行,主要还是处于安全的考虑
ZygoteHooks.startZygoteNoThreadCreation();
... ...
final Runnable caller;
try {
... ...
RuntimeInit.enableDdms();

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.");
}

zygoteServer.registerServerSocketFromEnv(socketName); // 注册 server socket

if (!enableLazyPreload) {
preload(bootTimingsTraceLog); // 默认情况,预加载信息
} else {
// 延迟预加载,变更 Zygote 进程优先级为 NORMAL 级别,第一次 fork 时才会 preload
Zygote.resetNicePriority();
}
... ...
if (startSystemServer) {
// fork systemserver
Runnable r = forkSystemServer(abiList, socketName, zygoteServer);
if (r != null) {
r.run();
return;
}
}
caller = zygoteServer.runSelectLoop(abiList); // zygote 进程进入无限循环,处理请求
} catch (Throwable ex) {
throw ex;
} finally {
zygoteServer.closeServerSocket();
}

if (caller != null) {
caller.run();
}
}
}

Zygote.main 函数除了安全相关的内容外,最主要的工作就是注册 server socket预加载启动 systemserver进入无限循环处理请求消息

3.1 注册 server socket

从 Android O 开始,已经将注册 server socket 相关的工作抽象到 ZygoteServer.java 中了。

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
// frameworks/base/core/java/com/android/internal/os/ZygoteServer.java

void registerServerSocketFromEnv(String socketName) {
if (mServerSocket == null) {
int fileDesc;
// ANDROID_SOCKET_PREFIX 为 "ANDROID_SOCKET_",此处的 socket name,就是 zygote
final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;
try {
// 在 init.zygote.rc 被加载时,指定了名为 zygote 的 socket,在进程被创建时,
// 就会创建对应的文件描述符,并加入到环境变量中,因此,此时可以取出对应的环境变量。
String env = System.getenv(fullSocketName);
fileDesc = Integer.parseInt(env);
} catch (RuntimeException ex) {
throw new RuntimeException(fullSocketName + " unset or invalid", ex);
}

try {
FileDescriptor fd = new FileDescriptor();
fd.setInt$(fileDesc); // 获取 zygote socket 的文件描述符
mServerSocket = new LocalServerSocket(fd); // 将 socket 包装成一个 server socket
mCloseSocketFd = true;
} catch (IOException ex) {
throw new RuntimeException(
"Error binding to local socket '" + fileDesc + "'", ex);
}
}
}

跟踪 LocalServerSocket

1
2
3
4
5
6
7
8
9
10
11
12
// frameworks/base/core/java/android/net/LocalServerSocket.java

public class LocalServerSocket implements Closeable {
public LocalServerSocket(String name) throws IOException
{
impl = new LocalSocketImpl();
impl.create(LocalSocket.SOCKET_STREAM); // 创建 SOCKET_STREAM 类型的 AF_UNIX socket
localAddress = new LocalSocketAddress(name);
impl.bind(localAddress); // 绑定到指定地址
impl.listen(LISTEN_BACKLOG); // 开始监听
}
}

3.2 预加载

我们看看预加载的内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

static void preload(TimingsTraceLog bootTimingsTraceLog) {

beginIcuCachePinning(); // Pin ICU Data, 获取字符集转换资源等
preloadClasses(); // 读取文件 system/etc/preloaded-classes,然后通过反射加载对应的类
preloadResources(); // 负责加载一些常用的系统资源
nativePreloadAppProcessHALs();
preloadOpenGL(); // 图形相关
preloadSharedLibraries(); // 一些必要库
preloadTextResources(); // 语言相关的字符信息

WebViewFactory.prepareWebViewInZygote();
endIcuCachePinning();
warmUpJcaProviders(); // 安全相关的

sPreloadComplete = true;
}

为了让系统实际运行时更加流畅,在 zygote 启动时候,调用 preload 函数进行了一些预加载操作。Android 通过 zygote fork 的方式创建子进程。zygote 进程预加载这些类和资源,在 fork 子进程时,仅需要做一个复制即可。这样可以节约子进程的启动时间。

同时,根据 fork 的 copy-on-write 机制可知,有些类如果不做改变,甚至都不用复制,子进程可以和父进程共享这部分数据,从而省去不少内存的占用。

3.3 启动 SystemServer 进程

再来看看启动 SystemServer 的流程:

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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
// frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

private static Runnable forkSystemServer(String abiList, String socketName,
ZygoteServer zygoteServer) {
long capabilities = posixCapabilitiesAsBits(
OsConstants.CAP_IPC_LOCK,
OsConstants.CAP_KILL,
OsConstants.CAP_NET_ADMIN,
OsConstants.CAP_NET_BIND_SERVICE,
OsConstants.CAP_NET_BROADCAST,
OsConstants.CAP_NET_RAW,
OsConstants.CAP_SYS_MODULE,
OsConstants.CAP_SYS_NICE,
OsConstants.CAP_SYS_PTRACE,
OsConstants.CAP_SYS_TIME,
OsConstants.CAP_SYS_TTY_CONFIG,
OsConstants.CAP_WAKE_ALARM
);
... ...
/* Hardcoded command line to start the system server */
String args[] = {
"--setuid=1000",
"--setgid=1000",
"--setgroups=1001,1002,1003,1004,1005,1006,...,3007,3009,3010",
"--capabilities=" + capabilities + "," + capabilities,
"--nice-name=system_server",
"--runtime-args",
"com.android.server.SystemServer",
};
ZygoteConnection.Arguments parsedArgs = null;

int pid;

try {
// 将上面准备的参数,按照 ZygoteConnection 的风格进行封装
parsedArgs = new ZygoteConnection.Arguments(args);
ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);

boolean profileSystemServer = SystemProperties.getBoolean(
"dalvik.vm.profilesystemserver", false);
if (profileSystemServer) {
parsedArgs.runtimeFlags |= Zygote.PROFILE_SYSTEM_SERVER;
}

// 通过 fork "分裂" 出 system_server
pid = Zygote.forkSystemServer(
parsedArgs.uid, parsedArgs.gid,
parsedArgs.gids,
parsedArgs.debugFlags,
null,
parsedArgs.permittedCapabilities,
parsedArgs.effectiveCapabilities);
} catch (IllegalArgumentException ex) {
throw new RuntimeException(ex);
}

/* For child process */
if (pid == 0) {
// 处理 32_64 和 64_32 的情况
if (hasSecondZygote(abiList)) {
waitForSecondaryZygote(socketName);
}

// fork 时会 copy socket,system server 需要主动关闭
zygoteServer.closeServerSocket();
// SystemServer 进程处理自己的工作
return handleSystemServerProcess(parsedArgs);
}
return null;
}

3.4 处理请求信息

创建出 SystemServer 进程后,调用 ZygoteServer.runSelectLoop,处理 server socket 收到的命令

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
// frameworks/base/core/java/com/android/internal/os/ZygoteServer.java

Runnable runSelectLoop(String abiList) {
ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();

// 首先将 server socket 加入到 fds
fds.add(mServerSocket.getFileDescriptor());
peers.add(null);

while (true) {
// 每次循环,都重新创建需要监听的 pollFds
StructPollfd[] pollFds = new StructPollfd[fds.size()];
for (int i = 0; i < pollFds.length; ++i) {
pollFds[i] = new StructPollfd();
pollFds[i].fd = fds.get(i);
// 关注事件到来
pollFds[i].events = (short) POLLIN;
}
try {
// 等待事件到来
Os.poll(pollFds, -1);
} catch (ErrnoException ex) {
throw new RuntimeException("poll failed", ex);
}

// 注意这里是倒序的,即优先处理已建立链接的信息,后处理新建链接的请求
for (int i = pollFds.length - 1; i >= 0; --i) {
if ((pollFds[i].revents & POLLIN) == 0) {
continue;
}

// server socket 最先加入 fds, 因此这里是 server socket 收到数据
if (i == 0) {
// 收到新的建立通信的请求,建立通信连接
ZygoteConnection newPeer = acceptCommandPeer(abiList);
// 加入到 peers 和 fds, 即下一次也开始监听
peers.add(newPeer);
fds.add(newPeer.getFileDesciptor());
} else {
//其它通信连接收到数据
... ...
}
}
}
}

从上面代码可知,初始时 fds 中仅有 server socket,因此当有数据到来时,将执行 i 等于 0 的分支。此时,显然是需要创建新的通信连接,因此 acceptCommandPeer 将被调用。

我们看看 acceptCommandPeer 函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// frameworks/base/core/java/com/android/internal/os/ZygoteServer.java

private ZygoteConnection acceptCommandPeer(String abiList) {
try {
// socket 编程中,accept() 调用主要用在基于连接的套接字类型,
// 比如 SOCK_STREAM 和 SOCK_SEQPACKET,它提取出所监听套接字的等待连接队列中第一个连接请求,
// 创建一个新的套接字,并返回指向该套接字的文件描述符,新建立的套接字不在监听状态,
// 原来所监听的套接字的状态也不受 accept() 调用的影响。
return createNewConnection(mServerSocket.accept(), abiList);
} catch (IOException ex) {
throw new RuntimeException("IOException during accept()", ex);
}
}

protected ZygoteConnection createNewConnection(LocalSocket socket, String abiList)
throws IOException {
return new ZygoteConnection(socket, abiList);
}

从上面的代码,可以看出 acceptCommandPeer 调用了 LocalServerSocket.accpet 函数。于是当新的连接建立时,zygote 将会创建出一个新的 socket 与其通信,并将该 socket 加入到 fds 中。因此,一旦通信连接建立后,fds 中将会包含有多个 socket。

当 poll 监听到这一组 sockets 上有数据到来时,就会从阻塞中恢复。于是,我们需要判断到底是哪个 socket 收到了数据。

runSelectLoop 中采用倒序的方式轮询。由于 server socket 第一个被加入到 fds,因此最后轮询到的 socket 才需要处理新建连接的操作;其它 socket 收到数据时,仅需要调用 zygoteConnection 的 runonce 函数执行数据对应的操作。若一个连接处理完所有对应消息后,该连接对应的 socket 和连接等将被移除。

四、总结

Zygote 启动流程到此结束,共做了如下几件事:

       ✎  1. 创建 AppRuntime 并调用其 start 方法,启动 Zygote 进程。
       ✎  2. 创建 JavaVM 并为 JavaVM 注册 JNI
       ✎  3. 通过 JNI 调用 ZygoteInitmain 函数进入 Zygote 的 Java 层
       ✎  4. 通过 registerZygoteSocket 函数创建 服务端 Socket,预加载类和资源,并通过 runSelectLoop 函数等待如 ActivityManagerService 等的请求。
       ✎  5. 启动 SystemServer 进程。