Zygote启动过程

Zygotesystem_server是Android系统中最重要的两个进程,任何一个进程的死亡都会导致Java世界的崩溃。其中,zygote由linux系统的1号进程init直接fork而来,而system_server进程由zygote进程fork而来。
通过adb shell连接到设备,可以进行验证:

Zygote本身是一个Native应用程序,与驱动、内核等均无关系。

Zygote是init进程根据init.rc文件中的配置项创建的,在当前最新的Android源码中,与zygote启动相关的代码不再是直接写在init.rc中,而是在init.rc文件开头以import /init.${ro.zygote}.rc的方式引入,对于不同的平台,引入的{ro.zygote}.rc文件是不同的,如图:

这4个文件的区别如下:

①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

打开init.zygote64.rc文件,内容如下:

1
2
3
4
5
6
7
8
service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server
class main
socket zygote stream 660 root system
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart media
onrestart restart netd
writepid /dev/cpuset/foreground/tasks /sys/fs/cgroup/stune/foreground/tasks

init.zygote32_64.rc的内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
service zygote /system/bin/app_process32 -Xzygote /system/bin --zygote --start-system-server --socket-name=zygote
class main
socket zygote stream 660 root system
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart media
onrestart restart netd
writepid /dev/cpuset/foreground/tasks /sys/fs/cgroup/stune/foreground/tasks

service zygote_secondary /system/bin/app_process64 -Xzygote /system/bin --zygote --socket-name=zygote_secondary
class main
socket zygote_secondary stream 660 root system
onrestart restart zygote
writepid /dev/cpuset/foreground/tasks /sys/fs/cgroup/stune/foreground/tasks

可以看到,这两个文件每个service第一行service zygote后面的路径是有区别的,分别是/system/bin/app_process64或是/system/bin/app_process32。这段代码表明,在不同的平台上zygote对应的可执行文件是不同的,在运行过程中app_processXX通过Linux下的pctrl系统调用将自己的名字换成了zygote

app_processXX对应的源文件是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
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
int main(int argc, char* const argv[])
{
/*设置当前进程和子进程不能获取更多权限*/
if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) < 0) {
// Older kernels don't understand PR_SET_NO_NEW_PRIVS and return
// EINVAL. Don't die on such kernels.
if (errno != EINVAL) {
LOG_ALWAYS_FATAL("PR_SET_NO_NEW_PRIVS failed: %s", strerror(errno));
return 12;
}
}

/*
寻找虚拟机相关参数,argv[0]肯定不是,所以直接忽略它。
由于我们在init.rc中设置的启动参数为
-Xzygote /system/bin --zygote --start-system-server
所以,这里找到的虚拟机参数就是-Xzygote
*/
AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
argc--;
argv++;
int i;
for (i = 0; i < argc; i++) {
if (argv[i][0] != '-') {
break;
}
if (argv[i][1] == '-' && argv[i][2] == 0) {
++i; // Skip --.
break;
}
runtime.addOption(strdup(argv[i]));
}


bool zygote = false;
bool startSystemServer = false;
bool application = false;
String8 niceName;
String8 className;

++i; /* `/system/bin`是parent dir,这个参数暂时没有用处,直接跳过 */
while (i < argc) {
/* 设置internal arguments */
const char* arg = argv[i++];
if (strcmp(arg, "--zygote") == 0) {
zygote = true;
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;
}
}

Vector<String8> args;
if (!className.isEmpty()) {
// We're not in zygote mode, the only argument we need to pass
// to RuntimeInit is the application argument.
//
// The Remainder of args get passed to startup class main(). Make
// copies of them before we overwrite them with the process name.
args.add(application ? String8("application") : String8("tool"));
runtime.setClassNameAndArgs(className, argc - i, argv + i);
} else {
// We're in zygote mode.
maybeCreateDalvikCache();

if (startSystemServer) {
args.add(String8("start-system-server"));
}

char prop[PROP_VALUE_MAX];
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=");
abiFlag.append(prop);
args.add(abiFlag);

// In zygote mode, pass all remaining arguments to the zygote
// main() method.
for (; i < argc; ++i) {
args.add(String8(argv[i]));
}
}

if (!niceName.isEmpty()) {
/* 将传递给runtime对象的启动参数app_process或app_process64替换为"zygote",
并把进程名也设置为"zygote" */
runtime.setArgv0(niceName.string());
set_process_name(niceName.string());
}

if (zygote) {
InitializeNativeLoader();

/* 启动java类ZygoteInit,并传入参数args
zygote仅用来在runtime.start()函数中区分是否以zygote模式启动 */
runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
} else if (className) {
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.");
return 10;
}
}

这里很关键的就是runtime.start()方法,runtime是一个AppRuntime对象,而AppRuntime类的大致结构如下:

1
2
3
4
5
6
7
8
9
10
11
12
class AppRuntime : public AndroidRuntime
{
public:
AppRuntime(char* argBlockStart, const size_t argBlockLength)
: AndroidRuntime(argBlockStart, argBlockLength){}

void setClassNameAndArgs(const String8& className, int argc, char * const *argv);
virtual void onVmCreated(JNIEnv* env);
virtual void onStarted();
virtual void onZygoteInit();
virtual void onExit(int code);
};

可以看到,AppRuntime实际上是继承自AndroidRuntime,并且没有override父类的start()方法,说明上面提到的runtime.start()实际是直接调用了AndroidRuntime的start()方法。

找到AndroidRuntime.cpp文件,它的start()方法部分代码如下:

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
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
ALOGD(">>>>>> START %s uid %d <<<<<<\n",
className != NULL ? className : "(unknown)", getuid());

static const String8 startSystemServer("start-system-server");

/*
* 'startSystemServer == true' means runtime is obsolete and not run from
* init.rc anymore, so we print out the boot start event here.
*/

for (size_t i = 0; i < options.size(); ++i) {
if (options[i] == startSystemServer) {
/* track our progress through the boot sequence */
const int LOG_BOOT_PROGRESS_START = 3000;
LOG_EVENT_LONG(LOG_BOOT_PROGRESS_START, ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));
}
}

/* 如果找不到环境变量ANDROID_ROOT,则新增环境变量ANDROID_ROOT值为"/system" */
const char* rootDir = getenv("ANDROID_ROOT");
if (rootDir == NULL) {
rootDir = "/system";
if (!hasDir("/system")) {
LOG_FATAL("No root directory specified, and /android does not exist.");
return;
}
setenv("ANDROID_ROOT", rootDir, 1);
}

/* ①创建虚拟机 */
JniInvocation jni_invocation;
jni_invocation.Init(NULL);
JNIEnv* env;
if (startVm(&mJavaVM, &env, zygote) != 0) {
return;
}
onVmCreated(env);

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

/* 创建一个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);
}

/*
③这里的className值为"com.android.internal.os.ZygoteInit"。
首先使用GetStaticMethodID()方法查找ZygoteInit类的main()方法,
如果main()方法存在,则使用CallStaticVoidMethod()方法来调用ZygoteInit类的main()方法,
从此,我们从Navtive世界进入java世界。
本线程会成为虚拟机主线程,并且不会return,直到虚拟机退出。
*/

char* slashClassName = toSlashClassName(className);
jclass startClass = env->FindClass(slashClassName);
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");
if (startMeth == NULL) {
ALOGE("JavaVM unable to find main() in '%s'\n", className);
/* keep going */
} else {
env->CallStaticVoidMethod(startClass, startMeth, strArray);

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

上面的代码包含了3个关键步骤,即:
①创建虚拟机
②注册JNI函数
③调用com.android.internal.os.ZygoteInit的main()方法,进入Java世界

com.android.internal.os.ZygoteInit的main()方法是从native世界进入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
//ZygoteInit.java
public static void main(String argv[]) {
try {
......

/* ①注册zygote使用的socket */
registerZygoteSocket(socketName);
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
SystemClock.uptimeMillis());

/* ②预加载类和资源 */
preload();

......

/* ③启动system_server进程 */
if (startSystemServer) {
startSystemServer(abiList, socketName);
}

......

/* ④运行zygote进程的select循环,当有新的连接请求时就接受 */
runSelectLoop(abiList);

closeServerSocket();
} catch (MethodAndArgsCaller caller) {
/* ⑤在system_serer进程中,以反射方式调用SystemServer类的main方法 */
caller.run();
} catch (RuntimeException ex) {
Log.e(TAG, "Zygote died with exception", ex);
closeServerSocket();
throw ex;
}
}

上面的代码有5个关键步骤都已标出。
①注册socket的代码比较简单,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
private static void registerZygoteSocket(String socketName) {
if (sServerSocket == null) {
int fileDesc;
final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;
try {
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);
sServerSocket = new LocalServerSocket(fd);
} catch (IOException ex) {
throw new RuntimeException(
"Error binding to local socket '" + fileDesc + "'", ex);
}
}
}

②预加载类的preload()方法代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
static void preload() {
Log.d(TAG, "begin preload");
preloadClasses();
preloadResources();
preloadOpenGL();
preloadSharedLibraries();
preloadTextResources();
// Ask the WebViewFactory to do any initialization that must run in the zygote process,
// for memory sharing purposes.
WebViewFactory.prepareWebViewInZygote();
Log.d(TAG, "end preload");
}

可以看到,这个方法的工作不少,包括预加载类、资源、OpenGL、共享库、文本资源、WebView等。
其中,预加载类这一步会去加载/system/etc/preloaded-classes文件中的类,该文件内容如下:


android.graphics.Bitmap
android.graphics.Bitmap$1
android.graphics.Bitmap$BitmapFinalizer
android.graphics.Bitmap$Config
android.graphics.BitmapFactory
android.graphics.BitmapFactory$Options
android.graphics.BitmapRegionDecoder
android.graphics.BitmapShader
android.graphics.BlurMaskFilter
android.graphics.Camera
android.graphics.Canvas
android.graphics.Canvas$CanvasFinalizer
android.graphics.Canvas$EdgeType
android.graphics.CanvasProperty
android.graphics.Color
android.graphics.ColorFilter
android.graphics.ColorMatrixColorFilter
android.graphics.ComposePathEffect
android.graphics.ComposeShader
android.graphics.CornerPathEffect
android.graphics.DashPathEffect

而这个preloaded-classes文件总共有3825行,可见预加载这一步会非常耗时。

③调用startSystemServer(abiList, socketName)方法创建system_server进程。system_server是framework的核心,如果它死了,就会导致zygote自杀。下面是startSystemServer()方法的代码:

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
private static boolean startSystemServer(String abiList, String socketName)
throws MethodAndArgsCaller, RuntimeException {

long capabilities = posixCapabilitiesAsBits(
OsConstants.CAP_BLOCK_SUSPEND,
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_RESOURCE,
OsConstants.CAP_SYS_TIME,
OsConstants.CAP_SYS_TTY_CONFIG
);
/* 硬编码相关启动参数 */
String args[] = {
"--setuid=1000",
"--setgid=1000",
"--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1032,3001,3002,3003,3006,3007",
"--capabilities=" + capabilities + "," + capabilities,
"--nice-name=system_server",//设置进程名为system_server
"--runtime-args",
"com.android.server.SystemServer",//实际启动的类
};
ZygoteConnection.Arguments parsedArgs = null;

int pid;

try {
parsedArgs = new ZygoteConnection.Arguments(args);
ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);

/* 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);
}

/* 对于子进程,也就是system_server,进入下面的代码 */
if (pid == 0) {
/* 参考本文最开头的init.zygote32_64.rc文件,会启动2个zygote,第二个的名字是"zygote_secondary" */
if (hasSecondZygote(abiList)) {
waitForSecondaryZygote(socketName);
}

/* 把剩下的工作交给system_server进程处理 */
handleSystemServerProcess(parsedArgs);
}

return true;
}

从上面的代码可以看到,通过调用Zygote.forkSystemServer()方法,zygote分裂出了一个system_server进程。

④zygote从startSystemServer()方法返回后,接着会调用runSelectLoop()方法,代码如下:

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
private static void runSelectLoop(String abiList) throws MethodAndArgsCaller {
ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();

fds.add(sServerSocket.getFileDescriptor());
peers.add(null);

while (true) {
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;
}
if (i == 0) {
/* 等待并接受客户端的连接请求 */
ZygoteConnection newPeer = acceptCommandPeer(abiList);
peers.add(newPeer);
fds.add(newPeer.getFileDesciptor());
} else {
/* 将客户端的后续请求交给ZygoteConnection的runOnce()方法处理 */
boolean done = peers.get(i).runOnce();
if (done) {
peers.remove(i);
fds.remove(i);
}
}
}
}
}

⑤在catch到MethodAndArgsCaller异常后,此时会处于system_serer进程中,以反射方式调用SystemServer类的main方法。这一步对于system_server的启动是至关重要的一步,会在下一篇《system_server启动过程》中详细分析。

《深入理解Android:卷I》对zygote的总结非常精辟:

zygote是在Android系统中创建java世界的盘古,它创建了第一个java虚拟机,同时它又是女娲,它成功地繁殖了framework的核心system_server进程,下面是zygote创建java世界的步骤:
◼︎第一天:创建AppRuntime对象,并调用它的start。此后的活动则由AppRuntime来控制。
◼︎第二天:调用startVm创建Java虚拟机,然后调用startReg来注册JNI函数。
◼︎第三天:通过JNI调用com.android.internal.os.ZygoteInit类的main函数,从此进入java世界。然而在这个世界刚开创的时候,什么东西都没有。
◼︎第四天:调用registerZygoteSocket。通过这个函数,它可以相应子孙后代的请求。同时zygote调用prelaod()为Java世界添砖加瓦。
◼︎第五天:zygote觉得自己的工作压力太大,便通过调用startSystemServer分裂一个子进程system_server来为Java世界服务。
◼︎第六天:zygote完成了Java世界的初创工作,它已经很满足了。下一步该做的就是调用runSelectLoopMode后,便沉沉睡去了。
以后的日子:zygote随时守护在我们的周围,当接收到子孙后代的请求时,它会随时醒来,为它们工作。

文章目录