Android Framework(一)——关键系统进程启动过程

注意(WARNING):本文含有大量AOSP源码,阅读过程中如出现头晕、目眩、恶心、犯困等症状属正常情况,作者本人亦无法避免症状产生,故不承担任何法律责任。

本文所贴源码全部来自 Android API 29 Platform,即 Android 10.0。

阅读本文需要有一定的C/C++基础。

Android系统架构

当我们看到”Android系统架构“这几个字时,通常会联想到Google官方发布的五层系统架构图,如下所示。

Google官方Android系统架构图

通过这张图我们可以理解Android系统如何分层以及各层功能职责,不过对于各层的运行细节、层与层之间如何进行通信和配合工作等我们还是无法得知。

为了窥探Android系统的全貌,我们可以从一些关键进程的启动入手,分析Android内部的环环相扣的内在联系。

这里借用gityuan大佬的一张图:

Android系统启动架构图(图源gityuan.com)

从上图我们可以看到整个系统启动中有几个关键进程:

  • Init进程
  • Zygote进程
  • System Server进程
  • 应用程序进程

下面我们根据这些进程的启动顺序来分析各进程的启动过程以及其主要工作,为了防止篇幅过长,应用程序进程将会在后面的文章单独分析。

Init进程

要了解Init进程,首先要知道Android系统的启动过程,分为几个步骤:

  1. 启动电源以及系统系统:当电源按下时引导芯片代码从预定义的地方(固化在 ROM)开始执行。加载引导程序BootLoader到RAM中,然后执行。
  2. 引导程序BootLoader:引导程序BootLoader是在Android操作系统开始运行前的一个小程序,它的主要作用是把系统OS拉起来并运行。
  3. Linux Kernel启动:当内核启动时,设置缓存、被保护存储器、计划列表、加载驱动。在内核完成系统设置后,它首先在系统文件中寻找init.rc文件,并启动init进程。
  4. Init 进程启动:init进程做的工作比较多 ,主要用来初始化和启动属性服务,也用来启动 Zygote 进程。

Init进程是Linux系统中用户空间的第一个进程,pid固定为1。

Init进程的入口函数

Init进程启动后执行其main方法,对应源码在 system/core/init/main.cpp 文件中:

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
// system/core/init/main.cpp
int main(int argc, char** argv) {
#if __has_feature(address_sanitizer)
__asan_set_error_report_callback(AsanReportCallback);
#endif
// Boost prio which will be restored later
setpriority(PRIO_PROCESS, 0, -20);
// ueventd主要是负责设备节点的创建、权限设定等一系列工作
if (!strcmp(basename(argv[0]), "ueventd")) {
return ueventd_main(argc, argv);
}

if (argc > 1) {
// //参数为subcontext,初始化日志系统
if (!strcmp(argv[1], "subcontext")) {
android::base::InitLogging(argv, &android::base::KernelLogger);
const BuiltinFunctionMap& function_map = GetBuiltinFunctionMap();

return SubcontextMain(argc, argv, &function_map);
}

// 参数为selinux_setup,启动Selinux安全策略
if (!strcmp(argv[1], "selinux_setup")) {
return SetupSelinux(argv);
}

// 参数为second_stage,进行第二阶段
if (!strcmp(argv[1], "second_stage")) {
return SecondStageMain(argc, argv);
}
}
// 默认进行第一阶段
return FirstStageMain(argc, argv);
}

// system/core/init/first_stage_init.cpp
int FirstStagetMain(int argc, char** argv) {
// init crash时重启引导加载程序
// 这个函数主要作用将各种信号量,如SIGABRT,SIGBUS等的行为设置为SA_RESTART,一旦监听到这些信号即执行重启系统
if (REBOOT_BOOTLOADER_ON_PANIC) {
InstallRebootSignalHandlers();
}
···
// 主要是创建挂载相关文件目录
CHECKCALL(mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755"));
CHECKCALL(mkdir("/dev/pts", 0755));
CHECKCALL(mkdir("/dev/socket", 0755));
CHECKCALL(mount("devpts", "/dev/pts", "devpts", 0, NULL));
#define MAKE_STR(x) __STRING(x)
CHECKCALL(mount("proc", "/proc", "proc", 0, "hidepid=2,gid=" MAKE_STR(AID_READPROC)));
...
// 传入selinux_setup-->main.cpp
const char* path = "/system/bin/init";
const char* args[] = {path, "selinux_setup", nullptr};
execv(path, const_cast<char**>(args));
...
}

// system/core/init/selinux.cpp
int SetupSelinux(char** argv) {
// 设置SELinux, 执行一些安全策略
SelinuxSetupKernelLogging();
SelinuxInitialize();

···

// 传入second_stage-->main.cpp
const char* path = "/system/bin/init";
const char* args[] = {path, "second_stage", nullptr};
execv(path, const_cast<char**>(args));
}

// 第二阶段
// system/core/init/init.cpp
int SecondStageMain(int argc, char** argv) {
···
// 初始化内核Logging
InitKernelLogging(argv);
···
// 初始化属性服务
PropertyInit();

···

// Now set up SELinux for second stage.
SelinuxSetupKernelLogging();
···

// 装载子进程信号处理,为了防止僵尸子进程无法回收
InstallSignalFdHandler(&epoll);
InstallInitNotifier(&epoll);
// 开启属性服务
StartPropertyService(&property_fd);
···
// 加载解析init.rc脚本
LoadBootScripts(am, sm);
···
return 0;
}

// 解析init.rc文件
static void LoadBootScripts(ActionManager& action_manager, ServiceList& service_list) {
// 构造一个解析器
Parser parser = CreateParser(action_manager, service_list);
std::string bootscript = GetProperty("ro.boot.init_rc", "");
if (bootscript.empty()) {
parser.ParseConfig("/init.rc");
}
...
}

main方法中通过判断参数个数以及类型来执行对应的代码,主要分为两个阶段的工作:

  • 第一阶段(FirstStageMain)
    • ueventd/watchdogd跳转及环境变量设置
    • 挂载文件系统并创建目录
    • 初始化日志输出、挂载分区设备
    • 启用SELinux安全策略
    • 初始化内核log系统
  • 第二阶段(SecondStageMain)
    • 创建进程会话密钥并初始化属性系统
    • 执行SELinux第二阶段并恢复一些文件安全上下文
    • 新建epoll并初始化子进程终止信号处理函数
    • 设置其他系统属性并开启属性服务
    • 解析init.rc脚本文件,启动Zygote进程和其它进程

解析init.rc文件

init.rc是一个配置文件,内部是由Android初始化语言编写的脚本,主要包含五种类型语句:

  • Action
  • Command
  • Service
  • Option
  • Import

我们只需要关注service命令即可。service命令可以开启一个服务,格式如下:

service <name><pathname> [<argument>]* <option> <option>

参数含义如下表所示。

参数 含义
<name> 表示此服务的名称
<pathname> 服务所在路径
<argument> 启动服务所带的参数
<option> 对此服务的约束选项

Init进程在解析init.rc文件时,会创建和启动service命令指定的进程,其中Zygote进程就是这样被启动的。

init.rc文件中通过import来导入对应Zygote的rc文件,主流厂商使用的是init.zygote64_32.rc,完整路径如下:

system/core/rootdir/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
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 usap_pool_primary stream 660 root system
onrestart exec_background - system system -- /system/bin/vdc volume abort_fuse
onrestart write /sys/power/state on
onrestart restart audioserver
onrestart restart cameraserver
onrestart restart media
onrestart restart netd
onrestart restart wificond
task_profiles ProcessCapacityHigh MaxPerformance
critical window=${zygote.critical_window.minute:-off} target=zygote-fatal

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
task_profiles ProcessCapacityHigh MaxPerformance

下面我们来分析下这段脚本。

Zygote进程

init.zygote64_32.rc文件包含两个service指令,对应两个Zygote进程。

第一个Zygote进程

第一个Zygote进程的进程名为zygote,进程通过/system/bin/app_process64来启动,并且会创建一个名为zygote的socket。

对应脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server --socket-name=zygote
class main
priority -20
user root // 用户为root
group root readproc reserved_disk // 访问组
socket zygote stream 660 root system // 创建一个socket,名字叫zygote,以tcp形式
socket usap_pool_primary stream 660 root system
onrestart exec_background - system system -- /system/bin/vdc volume abort_fuse
onrestart write /sys/power/state on // onrestart 指当进程重启时执行后面的命令
onrestart restart audioserver
onrestart restart cameraserver
onrestart restart media
onrestart restart netd
onrestart restart wificond
task_profiles ProcessCapacityHigh MaxPerformance
critical window=${zygote.critical_window.minute:-off} target=zygote-fatal

通过执行进行/system/bin/app_process64并传入4个参数启动Zygote进程,这五个参数分别是:

  • -Xzygote:该参数将作为虚拟机启动时所需的参数
  • /system/bin:代表虚拟机程序所在目录
  • –zygote:指明以ZygoteInit.java类中的main函数作为虚拟机执行入口
  • –start-system-server:告诉Zygote进程启动systemServe进程
  • –socket-name:指定socket的名字

第二个Zygote进程

第一个Zygote进程的进程名为zygote_secondary,进程通过/system/bin/app_process32来启动,并且会创建一个名为zygote_secondary的socket。

对应脚本:

1
2
3
4
5
6
7
8
9
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
task_profiles ProcessCapacityHigh MaxPerformance

可以看到Zygote进程通过/system/bin/app_process64和/system/bin/app_process32来启动,入口函数位于frameworks/base/cmds/app_process/app_main.cpp中。

Zygote进程入口函数

frameworks/base/cmds/app_process/app_main.cpp

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
int main(int argc, char* const argv[]){
···
// 构造AppRuntime
AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
argc--;
argv++;
···
// while循环拼接参数:根据init.rc中的配置,这里zygote=true
// 是否为zygote进程
bool zygote = false;
// 是否启动SystemServer进程
bool startSystemServer = false;
// 是否为应用进程
bool application = false;
// 进程名
String8 niceName;
// 入口类名
String8 className;
while (i < argc) {
const char* arg = argv[i++];
if (strcmp(arg, "--zygote") == 0) {
zygote = true;
// 为进程取一个名字,这里为zygote64
niceName = ZYGOTE_NICE_NAME;
} else if (strcmp(arg, "--start-system-server") == 0) {
startSystemServer = true;
} else if (strcmp(arg, "--application") == 0) {
application = true;
} else if (strncmp(arg, "--nice-name=", 12) == 0) {
niceName.setTo(arg + 12);
} else if (strncmp(arg, "--", 2) != 0) {
className.setTo(arg);
break;
} else {
--i;
break;
}
}
···
// 根据前面init.rc指定传入参数
if (zygote) {
// 本次流程进入此分支,加载ZygoteInit
runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
} else if (className) {
//如果是application启动模式,则加载RuntimeInit
runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
} else {
fprintf(stderr, "Error: no class name or --zygote supplied.\n");
app_usage();
LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
}
}

main方法中主要是创建了一个AppRuntime对象,然后根据传入的参数判断当前进程类型,可能为Zygote或者应用进程,本次流程为Zygote进程。最后进行参数的拼接,调用AppRuntime.start方法启动虚拟机并传入参数。

AppRuntime#start

AppRuntime继承自AndroidRuntime,start方法定义在AndroidRuntime中,先看看此方法的注释以及声明:

1
2
3
4
5
6
7
8
9
/*
* Start the Android runtime. This involves starting the virtual machine
* and calling the "static void main(String[] args)" method in the class
* named by "className".
*
* Passes the main function two arguments, the class name and the specified
* options string.
*/
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)

通过注释我们知道这个方法主要干了两件事:

  • 启动Dalvik虚拟机
  • 调用”static void main(String[] args)“方法

下面来过一过源码。

frameworks/base/core/jni/AndroidRuntime.cpp

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
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
···
/* start the virtual machine */
// 初始化JNI,会创建虚拟机
JniInvocation jni_invocation;
jni_invocation.Init(NULL);
JNIEnv* env;
// 启动Dalvik虚拟机,主要是设置一大堆启动参数
if (startVm(&mJavaVM, &env, zygote, primary_zygote) != 0) {
return;
}
// 启动成功回调
onVmCreated(env);

// 注册JNI函数
if (startReg(env) < 0) {
ALOGE("Unable to register all android natives\n");
return;
}
···

// 启动Java main方法需要一个String[]类型的参数
// 在这里构建这个参数
jclass stringClass;
jobjectArray strArray;
jstring classNameStr;

stringClass = env->FindClass("java/lang/String");
assert(stringClass != NULL);
strArray = env->NewObjectArray(options.size() + 1, stringClass, NULL);
assert(strArray != NULL);
classNameStr = env->NewStringUTF(className);
assert(classNameStr != NULL);
env->SetObjectArrayElement(strArray, 0, classNameStr);

for (size_t i = 0; i < options.size(); ++i) {
jstring optionsStr = env->NewStringUTF(options.itemAt(i).string());
assert(optionsStr != NULL);
env->SetObjectArrayElement(strArray, i + 1, optionsStr);
}

/*
* Start VM. This thread becomes the main thread of the VM, and will
* not return until the VM exits.
*/

// 将"com.android.internal.os.ZygoteInit"转换为"com/android/internal/os/ZygoteInit"
char* slashClassName = toSlashClassName(className != NULL ? className : "");
jclass startClass = env->FindClass(slashClassName);
if (startClass == NULL) {
ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
/* keep going */
} else {
// 获取main方法jmethodID
jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
"([Ljava/lang/String;)V");
if (startMeth == NULL) {
ALOGE("JavaVM unable to find main() in '%s'\n", className);
/* keep going */
} else {
// Native调用Java main方法,至此进入Java世界
env->CallStaticVoidMethod(startClass, startMeth, strArray);

#if 0
if (env->ExceptionCheck())
threadExitUncaughtException(env);
#endif
}
}
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");
}

这段代码配合注释还是很容易理解的,首先初始化了JNI服务,然后启动了Dalvik虚拟机,最后根据传入的className,使用JNI方式调用ZygoteInit#main方法。

ZygoteInit#main

代码执行到这里的时候,我们已经从晦涩的C++世界进入了熟悉的Java世界中。

来到ZygoteInit.java类,找到对应的Java main方法,此方法的主要工作为:

  1. 预加载类和资源
  2. 创建服务端Socket
  3. 启动SystemServer进程
  4. 开启循环,等待客户端请求

下面通过源码来分析这四个步骤。

frameworks/base/core/java/com/android/internal/os/ZygoteInit.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
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
public static void main(String argv[]) {
// 创建ZygoteServer
ZygoteServer zygoteServer = null;

// 调用native函数,确保当前没有其它线程在运行
ZygoteHooks.startZygoteNoThreadCreation();

// Zygote goes into its own process group.
try {
// 设置Zygote的pid和gid为0
Os.setpgid(0, 0);
} catch (ErrnoException ex) {
throw new RuntimeException("Failed to setpgid(0,0)", ex);
}

Runnable caller;
try {
···
// 得到systrace的监控TAG
String bootTimeTag = Process.is64Bit() ? "Zygote64Timing" : "Zygote32Timing";
// 通过systradce来追踪 函数ZygoteInit
TimingsTraceLog bootTimingsTraceLog = new TimingsTraceLog(bootTimeTag,
Trace.TRACE_TAG_DALVIK);
bootTimingsTraceLog.traceBegin("ZygoteInit");
// 开启DDMS(Dalvik Debug Monitor Service)功能
// 注册所有已知的Java VM的处理块的监听器。线程监听、内存监听、native 堆内存监听、debug模式监听等等
RuntimeInit.enableDdms();

boolean startSystemServer = false;
String zygoteSocketName = "zygote";
String abiList = null;
boolean enableLazyPreload = false;

// 解析传入main方法的参数
for (int i = 1; i < argv.length; i++) {
if ("start-system-server".equals(argv[i])) {
// 启动zygote时才会传入,表示需要启动systemServer
startSystemServer = true;
} else if ("--enable-lazy-preload".equals(argv[i])) {
// 启动zygote_secondary时才会传入
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)) {
// 创建socket指定的名称,zygote或者zygote_secondary
zygoteSocketName = argv[i].substring(SOCKET_NAME_ARG.length());
} else {
throw new RuntimeException("Unknown command line argument: " + argv[i]);
}
}

// 判断需要创建的Socket类型
final boolean isPrimaryZygote = zygoteSocketName.equals(Zygote.PRIMARY_SOCKET_NAME);

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

// 在第一次zygote启动时,enableLazyPreload为false,执行preload
if (!enableLazyPreload) {
// systrace 追踪ZygotePreload
bootTimingsTraceLog.traceBegin("ZygotePreload");
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
SystemClock.uptimeMillis());
// 加载进程的资源和类
preload(bootTimingsTraceLog);
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
SystemClock.uptimeMillis());
bootTimingsTraceLog.traceEnd(); // ZygotePreload
} else {
Zygote.resetNicePriority();
}


bootTimingsTraceLog.traceBegin("PostZygoteInitGC");
gcAndFinalize();
bootTimingsTraceLog.traceEnd(); // PostZygoteInitGC

// 结束ZygoteInit的systrace追踪
bootTimingsTraceLog.traceEnd(); // ZygoteInit
// 禁用systrace追踪,以便fork的进程不会从zygote继承过时的跟踪标记
Trace.setTracingEnabled(false, 0);


Zygote.initNativeState(isPrimaryZygote);

ZygoteHooks.stopZygoteNoThreadCreation();

// 调用ZygoteServer构造函数,会根据传入的参数创建对应的socket
zygoteServer = new ZygoteServer(isPrimaryZygote);

if (startSystemServer) {
// fork出system server
Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);

// 这里r如果为null,则表示当前是zygote进程,那么就会继续执行下面的代码,开启循环
// 如果r不为null,则表示当前是子进程,那么就会直接执行子进程然后return
if (r != null) {
r.run();
return;
}
}

Log.i(TAG, "Accepting command socket connections");

// zygote进程进入无限循环,处理子进程请求
caller = zygoteServer.runSelectLoop(abiList);
} catch (Throwable ex) {
Log.e(TAG, "System zygote died with exception", ex);
throw ex;
} finally {
if (zygoteServer != null) {
zygoteServer.closeServerSocket();
}
}

// We're in the child process and have exited the select loop. Proceed to execute the
// command.
if (caller != null) {
caller.run();
}
}

可以看到Zygote实际上也是采用的C/S结构,它首先会使用预加载机制加载一些公
共的类和资源,这样子进程就无需再次加载。

然后通过ZygoteServer来创建本地服务端的socket,用于与其他进程通信。

在第一次启动时它会通过fork自身的方式启动SystemServer进程,然后会一直等待子进程Socket请求请求,通过fork zygote可以快速创建一个已经初始化好的”Java 世界进程“,这也是Zygote名称的由来。

下面我们来看看预加载方法。

ZygoteInit#preLoad

preLoad中大量使用了systrace来监控方法执行性能,这里我将它们去除掉了,源码如下:

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
static void preload(TimingsTraceLog bootTimingsTraceLog) {
// 用于Hook的函数,开始预载
beginPreload();

// 预加载类
// 列表位于/system/etc/preloaded-classes
preloadClasses();

// 加载一些无法放到启动类加载器Path路径下的类
cacheNonBootClasspathClassLoaders();

// 加载公用的资源文件,主要是图片和颜色
preloadResources();

// 预载硬件抽象层
nativePreloadAppProcessHALs();

// 预加载图形驱动
maybePreloadGraphicsDriver();

// 加载公用的类库
// android、compiler_rt、jnigraphics等library
preloadSharedLibraries();

// 加载公用的文字资源
preloadTextResources();

// 初始化Webview
WebViewFactory.prepareWebViewInZygote();
// 用于Hook的函数,完成预载
endPreload();
warmUpJcaProviders();

sPreloadComplete = true;
}

这些预加载的类都是Android中的一些关键类,整个列表定义在frameworks/base/config/preloaded-classes中,Android 10中一共有1万多个。资源主要是加载framework-res.apk中的资源、openGL以及WebView等,我们经常用的android.R文件就是来自这里。

预加载的好处是在fork创建子进程时无需再次创建这些类和资源,只需复制即可。

ZygoteInit#forkSystemServer

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
private static Runnable forkSystemServer(String abiList, String socketName,
ZygoteServer zygoteServer) {
···
ZygoteArguments parsedArgs;

int pid;

try {
ZygoteCommandBuffer commandBuffer = new ZygoteCommandBuffer(args);
try {
// 封装参数
parsedArgs = ZygoteArguments.getInstance(commandBuffer);
} catch (EOFException e) {
throw new AssertionError("Unexpected argument error for forking system server", e);
}
commandBuffer.close();
Zygote.applyDebuggerSystemProperty(parsedArgs);
Zygote.applyInvokeWithSystemProperty(parsedArgs);

if (Zygote.nativeSupportsMemoryTagging()) {
/* The system server has ASYNC MTE by default, in order to allow
* system services to specify their own MTE level later, as you
* can't re-enable MTE once it's disabled. */
String mode = SystemProperties.get("arm64.memtag.process.system_server", "async");
if (mode.equals("async")) {
parsedArgs.mRuntimeFlags |= Zygote.MEMORY_TAG_LEVEL_ASYNC;
} else if (mode.equals("sync")) {
parsedArgs.mRuntimeFlags |= Zygote.MEMORY_TAG_LEVEL_SYNC;
} else if (!mode.equals("off")) {
/* When we have an invalid memory tag level, keep the current level. */
parsedArgs.mRuntimeFlags |= Zygote.nativeCurrentTaggingLevel();
Slog.e(TAG, "Unknown memory tag level for the system server: \"" + mode + "\"");
}
} else if (Zygote.nativeSupportsTaggedPointers()) {
/* Enable pointer tagging in the system server. Hardware support for this is present
* in all ARMv8 CPUs. */
parsedArgs.mRuntimeFlags |= Zygote.MEMORY_TAG_LEVEL_TBI;
}

/* Enable gwp-asan on the system server with a small probability. This is the same
* policy as applied to native processes and system apps. */
parsedArgs.mRuntimeFlags |= Zygote.GWP_ASAN_LEVEL_LOTTERY;

if (shouldProfileSystemServer()) {
parsedArgs.mRuntimeFlags |= Zygote.PROFILE_SYSTEM_SERVER;
}

/* Request to fork the system server process */
pid = Zygote.forkSystemServer(
parsedArgs.mUid, parsedArgs.mGid,
parsedArgs.mGids,
parsedArgs.mRuntimeFlags,
null,
parsedArgs.mPermittedCapabilities,
parsedArgs.mEffectiveCapabilities);
} catch (IllegalArgumentException ex) {
throw new RuntimeException(ex);
}

/* For child process */
if (pid == 0) {
if (hasSecondZygote(abiList)) {
waitForSecondaryZygote(socketName);
}

zygoteServer.closeServerSocket();
return handleSystemServerProcess(parsedArgs);
}

return null;
}

forkSystemServer方法将会采用JNI的方式调用nativeForkSystemServer方法来创建子进程。在子进程中调用handleSystemServerProcess方法,会返回一个Runnale对象,通过调用这个Runnable的run方法来执行SystemServer的main方法。

ZygoteServer#runSelectLoop

在创建完SystemServer之后,Zygote的前置工作就已经完成,接下来将会进入无限循环中,等待SystemServer通知它创建App进程。runSelectLoop的源码较为复杂,这里做了大量精简,我们只需要关注关键方法即可。

frameworks/base/core/java/com/android/internal/os/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
28
29
30
31
32
33
34
35
36
37
Runnable runSelectLoop(String abiList) {

···

try {
// 利用管道机制阻塞等待事件
Os.poll(pollFDs, -1);
} catch (ErrnoException ex) {
throw new RuntimeException("poll failed", ex);
}

boolean usapPoolFDRead = false;

// 倒序处理,即优先处理已建立链接的信息,后处理新建链接的请求
while (--pollIndex >= 0) {
if ((pollFDs[pollIndex].revents & POLLIN) == 0) {
continue;
}

// server socket最先加入fds, 因此这里是server socket收到数据
if (pollIndex == 0) {
// 收到新的建立通信的请求,建立通信连接
ZygoteConnection newPeer = acceptCommandPeer(abiList);
// 加入到peers和fds, 即下一次也开始监听
peers.add(newPeer);
socketFDs.add(newPeer.getFileDescriptor());
} else if (pollIndex < usapPoolEventFDIndex) {
// 说明接收到AMS发送过来创建应用程序的请求,调用processOneCommand来创建新的应用程序进程
try {
//有socket连接,创建ZygoteConnection对象,并添加到fds
ZygoteConnection connection = peers.get(pollIndex);
// 处理连接
final Runnable command = connection.processOneCommand(
this);

···
}

ZygoteConnection#processOneCommand

frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Runnable processOneCommand(ZygoteServer zygoteServer) {
...
//fork子进程
pid = Zygote.forkAndSpecialize(parsedArgs.mUid, parsedArgs.mGid,
parsedArgs.mGids,
parsedArgs.mRuntimeFlags, rlimits, parsedArgs.mMountExternal,
parsedArgs.mSeInfo,
parsedArgs.mNiceName, fdsToClose, fdsToIgnore, parsedArgs.
mStartChildZygote,
parsedArgs.mInstructionSet, parsedArgs.mAppDataDir, parsedArgs
.mTargetSdkVersion);
if (pid == 0) {
zygoteServer.setForkChild();
// 子进程执行
return handleChildProc(parsedArgs, descriptors, childPipeFd,
parsedArgs.mStartChildZygote);
} else {
// 父进程执行
handleParentProc(pid, descriptors, serverPipeFd);
return null;
}
...
}

ZygoteConnection#handleChildProc

frameworks/base/core/java/com/android/internal/os/ZygoteConnection.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
28
29
30
private Runnable handleChildProc(ZygoteArguments parsedArgs,
FileDescriptor pipeFd, boolean isZygote) {

// 关闭继承自Zygote的Socket
closeSocket();

// 设置目标App进程名
Zygote.setAppProcessName(parsedArgs, TAG);

if (parsedArgs.mInvokeWith != null) {
WrapperInit.execApplication(parsedArgs.mInvokeWith,
parsedArgs.mNiceName, parsedArgs.mTargetSdkVersion,
VMRuntime.getCurrentInstructionSet(),
pipeFd, parsedArgs.mRemainingArgs);

// Should not get here.
throw new IllegalStateException("WrapperInit.execApplication unexpectedly returned");
} else {
if (!isZygote) {
// App进程,执行main方法
return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,
parsedArgs.mDisabledCompatChanges,
parsedArgs.mRemainingArgs, null /* classLoader */);
} else {
// 子Zygote进程初始化
return ZygoteInit.childZygoteInit(
parsedArgs.mRemainingArgs /* classLoader */);
}
}
}

小结

Zygote进程所做的工作有点多,我们来总结一下它的主要工作流程。

  1. 启动Android系统中第一个Java虚拟机,并且初始化了JNI,注册了Android中的JNI函数。
  2. 调用Java层ZygoteInit类的main函数,进入Java世界。
  3. 建立Socket服务端,用于与客户端进行IPC通信,主要是接收SystemServer的启动App进程请求。
  4. 预加载类、资源、Webview等。
  5. 通过fork自身的方式,启动SystemServer进程。
  6. 调用runSelectLoopMode方法,进入无限循环,等待创建子进程的请求。

System Server进程

SystemServer进程主要用于创建系统服务,我们熟知的 AMS、ATMS、WMS 和 PMS 都是由它来创建的,其进程名为“system_server”。

下面就继续跟踪上节的ZygoteInit#handleSystemServerProcess方法来分析SystemServer的工作流程。

ZygoteInit#handleSystemServerProcess

frameworks/base/core/java/com/android/internal/os/ZygoteInit.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
28
29
30
31
32
33
34
35
36
37
private static Runnable handleSystemServerProcess(ZygoteArguments parsedArgs) {

···

// 如果有参数中有--invokewith
if (parsedArgs.mInvokeWith != null) {
String[] args = parsedArgs.mRemainingArgs;
if (systemServerClasspath != null) {
String[] amendedArgs = new String[args.length + 2];
amendedArgs[0] = "-cp";
amendedArgs[1] = systemServerClasspath;
System.arraycopy(args, 0, amendedArgs, 2, args.length);
args = amendedArgs;
}

WrapperInit.execApplication(parsedArgs.mInvokeWith,
parsedArgs.mNiceName, parsedArgs.mTargetSdkVersion,
VMRuntime.getCurrentInstructionSet(), null, args);

throw new IllegalStateException("Unexpected return from WrapperInit.execApplication");
} else {
// 此次流程进入此分支
ClassLoader cl = null;
if (systemServerClasspath != null)
// 创建PathClassLoader
cl = createPathClassLoader(systemServerClasspath, parsedArgs.mTargetSdkVersion);

Thread.currentThread().setContextClassLoader(cl);
}

// 将剩余参数传递给SystemServer
return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,
parsedArgs.mDisabledCompatChanges,
parsedArgs.mRemainingArgs, cl);
}
/* should never reach here */
}

这里要注意的是,PathClassLoader在这里被创建。

接着调用了ZygoteInit#zygoteInit方法。

ZygoteInit#zygoteInit

zygoteInit方法接收3个参数:

  • targetSdkVersion:系统设置的目标SDK版本
  • disabledCompatChanges:禁用的一些兼容选项
  • argv:传递给虚拟机的启动参数,也就是main方法接收到的参数

源码如下:

frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public static Runnable zygoteInit(int targetSdkVersion, long[] disabledCompatChanges,
String[] argv, ClassLoader classLoader) {
if (RuntimeInit.DEBUG) {
Slog.d(RuntimeInit.TAG, "RuntimeInit: Starting application from zygote");
}

Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ZygoteInit");
// 重定向Log输出流
RuntimeInit.redirectLogStreams();
// 一些通用的初始化,例如log、时区、http userAgent等
RuntimeInit.commonInit();
// 关键方法1,启动Binder线程池
ZygoteInit.nativeZygoteInit();
// 关键方法2,执行Java main方法
return RuntimeInit.applicationInit(targetSdkVersion, disabledCompatChanges, argv,
classLoader);
}

此方法中有两个关键方法,已在代码中标明,下面就来分析下这两个方法。

ZygoteInit#nativeZygoteInit

nativeZygotelnit是一个Native方法,因此我们先要了解它对应的JNI文件,源码中的JNI文件都可以在 frameworks/base/core/jni 目录中找到。

frameworks/base/core/jni/AndroidRuntime.cpp

1
2
3
4
5
6
7
8
9
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));
}

通过JNI的gMethods数组,可以看出nativeZygotelnit方法对应的是JNI文件AndroidRuntime.cpp的com_android_internal_os_zygotelnit_nativeZygotelnit函数:

frameworks/base/core/jni/AndroidRuntime.cpp

1
2
3
4
5
6
static AndroidRuntime* gCurRuntime = NULL;

static void com_android_internal_os_ZygoteInit_nativeZygoteInit(JNIEnv* env, jobject clazz)
{
gCurRuntime->onZygoteInit();
}

可以看到gCurRuntime是AndroidRuntime的指针,指向的是子类AppRuntime,实际调用的是AppRuntime中的onZygoteInit方法:

frameworks/base/cmds/app_process/app_main.cpp

1
2
3
4
5
6
7
virtual void onZygoteInit()
{
sp<ProcessState> proc = ProcessState::self();
ALOGV("App process: starting thread pool.\n");
// 启动Binder线程池
proc->startThreadPool();
}

代码中调用了ProcessState#startThreadPool方法来启动Binder线程池,这里就不再深入了。

RuntimeInit#applicationInit

applicationInit方法主要是设置虚拟机的TargetSDKVersion,并且通过传递过来的参数找到并启动Java Main方法。

frameworks/base/core/java/com/android/internal/os/RuntimeInit.java

1
2
3
4
5
6
7
8
9
10
11
12
protected static Runnable applicationInit(int targetSdkVersion, long[] disabledCompatChanges,
String[] argv, ClassLoader classLoader) {
nativeSetExitWithoutCleanup(true);

VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);
VMRuntime.getRuntime().setDisabledCompatChanges(disabledCompatChanges);

final Arguments args = new Arguments(argv);

// 找到对应类的入口函数
return findStaticMain(args.startClass, args.startArgs, classLoader);
}

RuntimeInit#findStaticMain

findStaticMain使用反射创建的入口类,并调用main方法,注意这里的ClassLoader是我们上面提到过的PathClassLoader。

frameworks/base/core/java/com/android/internal/os/RuntimeInit.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
28
29
30
31
32
33
34
35
36
37
protected static Runnable findStaticMain(String className, String[] argv,
ClassLoader classLoader) {
Class<?> cl;

try {
cl = Class.forName(className, true, classLoader);
} catch (ClassNotFoundException ex) {
throw new RuntimeException(
"Missing class when invoking static main " + className,
ex);
}

Method m;
try {
m = cl.getMethod("main", new Class[] { String[].class });
} catch (NoSuchMethodException ex) {
throw new RuntimeException(
"Missing static main on " + className, ex);
} catch (SecurityException ex) {
throw new RuntimeException(
"Problem getting static main on " + className, ex);
}

int modifiers = m.getModifiers();
if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
throw new RuntimeException(
"Main method is not public and static on " + className);
}

/*
* This throw gets caught in ZygoteInit.main(), which responds
* by invoking the exception's run() method. This arrangement
* clears up all the stack frames that were required in setting
* up the process.
*/
return new MethodAndArgsCaller(m, argv);
}

方法返回了一个MethodAndArgsCaller对象,MethodAndArgsCaller是一个Runnable,它主要是调用了传入的Method对象,并将异常都强转为了RuntimeException和Error。

MethodAndArgsCaller将会返回到ZygoteInit#main方法中执行,接下来就进入了SystemServer.java的main方法中。

SystemServer#main

SystemServer的入口main函数位于SystemServer.java中。

frameworks/base/services/java/com/android/server/SystemServer.java

1
2
3
public static void main(String[] args) {
new SystemServer().run();
}

main方法只是常见了一个SystemServer对象并调用其run方法。

frameworks/base/services/java/com/android/server/SystemServer.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
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
private void run() {
TimingsTraceAndSlog t = new TimingsTraceAndSlog();
try {
t.traceBegin("InitBeforeStartServices");
···
// 省略设置一大堆虚拟机的系统属性
// 矫正时区等操作
···
// 清除JVM中的内存增长上限
VMRuntime.getRuntime().clearGrowthLimit();

// 设置binder线程池最大线程数,Android 10里面为31
BinderInternal.setMaxThreads(sMaxBinderThreads);

// 设置当前进程优先级
android.os.Process.setThreadPriority(
android.os.Process.THREAD_PRIORITY_FOREGROUND);
android.os.Process.setCanSelfBackground(false);

// 创建SystemServer进程的主线程Looper
Looper.prepareMainLooper();
Looper.getMainLooper().setSlowLogThresholdMs(
SLOW_DISPATCH_THRESHOLD_MS, SLOW_DELIVERY_THRESHOLD_MS);

SystemServiceRegistry.sEnableServiceNotFoundWtf = true;

// 加载android_servers.so库,初始化Native服务
System.loadLibrary("android_servers");

// 允许堆内存分析
initZygoteChildHeapProfiling();

// Debug模式下开启一条线程监听文件描述符泄露
if (Build.IS_DEBUGGABLE) {
spawnFdLeakCheckThread();
}

// Check whether we failed to shut down last time we tried.
// This call may not return.
performPendingShutdown();

// 创建系统上下文
createSystemContext();

// Call per-process mainline module initialization.
ActivityThread.initializeMainlineModules();

// 创建系统管理服务——SystemServiceManager
mSystemServiceManager = new SystemServiceManager(mSystemContext);
mSystemServiceManager.setStartInfo(mRuntimeRestart,
mRuntimeStartElapsedTime, mRuntimeStartUptime);
LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
// Prepare the thread pool for init tasks that can be parallelized
SystemServerInitThreadPool.start();
// Debug模式下绑定JVMTI Agent
if (Build.IS_DEBUGGABLE) {
···
}

// Setup the default WTF handler
RuntimeInit.setDefaultApplicationWtfHandler(SystemServer::handleEarlySystemWtf);

// Start services.
try {
t.traceBegin("StartServices");
// 启动引导服务
startBootstrapServices(t);
// 启动核心服务
startCoreServices(t);
// 启动其他服务
startOtherServices(t);
} catch (Throwable ex) {
Slog.e("System", "******************************************");
Slog.e("System", "************ Failure starting system services", ex);
throw ex;
} finally {
t.traceEnd(); // StartServices
}

···

// 开启Loop循环
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}

createSystemContext用于创建系统上下文,此方法中首先会创建ActivityThread对象,并且调用ActivityThread#attach方法,然后通过ActivityThread对象来构建SystemContext。

在启动服务之前,方法中首先创建了SystemServiceManager,由它负责创建、启动和管理服务。

接着通过三个方法来分别启动不同类型的服务:

  • startBootstrapServices:启动引导服务,包括Installer、ActivityManagerService、ActivityTaskManagerService、PackageManagerService等。
  • startCoreServices:启动核心服务,包括SystemConfigService、BatteryService、UsageStatsService、WebViewUpdateService等。
  • startOtherServices:启动其他服务,包括NetworkManagementService、NetworkStatsService、InputManagerService、TelephonyRegistry等。

实际上每个方法负责启动的服务还有很多,这里只是举例了几个常用的服务。

这些服务的启动逻辑是相似的,这里以Android 10新增的ActivityTaskManagerService为例,来演示一遍服务启动流程:

1
2
3
4
ActivityTaskManagerService atm =
mSystemServiceManager
.startService(ActivityTaskManagerService.Lifecycle.class)
.getService();

ActivityTaskManagerService的静态内部类Lifecycle继承自SystemService,其构造方法中会创建外部类ActivityTaskManagerService的实例。

SystemServiceManager#startService

frameworks/base/services/core/java/com/android/server/SystemServiceManager.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
private final ArrayList<SystemService> mServices = new ArrayList<SystemService>();    

public void startService(@NonNull final SystemService service) {
// 注册服务(添加到list中)
mServices.add(service);
long time = SystemClock.elapsedRealtime();
try {
// 调用onStart启动服务
service.onStart();
} catch (RuntimeException ex) {
throw new RuntimeException("Failed to start service " + service.getClass().getName()
+ ": onStart threw an exception", ex);
}
warnIfTooLong(SystemClock.elapsedRealtime() - time, service, "onStart");
}

ActivityTaskService.Lifecycle#onStart

frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java

1
2
3
4
5
6
7
8
9
10
11
12
// Lifecycle
public void onStart() {
// 注册到ServiceManager中供其他进程使用
publishBinderService(Context.ACTIVITY_TASK_SERVICE, mService);
mService.start();
}

// ActivityTaskManagerService
private void start() {
// 将内部类ActivityTaskManagerService$LocalService添加到本地服务中,供本地进程内使用
LocalServices.addService(ActivityTaskManagerInternal.class, mInternal);
}

此方法做了两件事:

  1. 将ActivityTaskManagerService对象注册到ServiceManager中,其他进程通过访问ServiceManager来获取ActivityTaskManagerService的代理对象。
  2. 将ActivityTaskManagerService的内部类LocalService添加到本地服务列表,LocalService不是一个IBinder对象,它用于当前进程内部使用ATMS服务。

小结

我们来总结一下SystemServer进程被创建后所做的工作:

  1. 启动Binder线程池,用于与其他进程进行Bind通信。
  2. 创建SystemServiceManager,用于启动、创建和管理服务。
  3. 启动各种系统服务,分为引导服务、核心服务和其他服务。

问题

下面通过几个问题来结束此篇又臭又长的文章。

Q:系统服务何时启动?如何启动?

A:在SystemServer进程启动时,会分批启动所有系统服务。

通过SystemServiceManager#startService来启动一个服务,服务启动后需要注册到ServiceManager中,其他进程访问ServiceManager来获取服务的代理对象。

Q:什么是Zygote预加载?

A:预加载是指在Zygote进程启动的时候就加载一些类库和资源文件,这样系统只需要在第一次启动Zygote时加载这些共用的资源,子进程创建时只需要复用即可无需再次加载。

这些资源被保存到全局变量Resources中,它是一个全局静态变量,可以通过 Resources.getSystem() 来使用它。

全局资源Resources

Q:系统中有几个Zygote进程?

A:按照我们上面的源码分析,系统中有两个Zygote进程,进程名分别为zygote和zygote64。

但如果我们使用adb shell ps查看真机上的进程时,会发现多了一个名为webview_zygote的进程,有时候还会有一个名为App包名_zygote的进程。

这两个进程实际上是由ZygoteProcess#startChildZygote创建而来,这些进程继承了Zygote中的数据,并且可以与Zygote连接。

创建它们的目的通常是明确的,例如WebViewZygtoe用于启动一个WebView进程。

不过按照通常意义来讲的Zygote进程最少一个最多两个。

Q:为什么SystemServer与Zygote进程之间的通信采用Unix Domain Sockt而不是Binder?

A:关键的原因有:

  • fork采用的是CopyOnWrite机制,由于可能存在的死锁问题,Unix禁止fork多线程程序。Zygote当然也是多线程的,除了主线程外还有4条守护线程,每次fork前都需要停止这些线程,待fork结束后重新执行。
  • Zygote进程先于SystemServer创建,如果要使用Binder,那么需要等待SystemServer创建完成之后再向SystemServer注册Binder服务,这里需要额外的同步操作。

Binder机制是需要建立Binder线程池的,代理对象对Binder的调用是在Binder线程池中,在通过线程间通信通知主线程。

例如Activity启动时,AMS的本地代理IApplicationThread运行在Binder线程池中,处理完毕后通过Handler通知ActivityThread来执行启动Activity的流程。

Zygote本身只需与SystemServer以及子Zygote进程通信,并不依赖多线程来提升性能,若使用Binder反而增加了Zygote中的线程数,使得性能下降。

Zygote中的线程

SystemServer不受到此限制,它并不需要fork自身来创建子进程,所以它会在第一时间初始化Binder线程池。

参考