Zygote进程为什么可以创建子进程,然后自己还一直存活着。
携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第1天,点击查看活动详情
首先简单分析下Zygote进程的启动流程:init.cpp
会去读取init.rc
内容,在init.rc
可以看到这么一句话:
import /system/etc/init/hw/init.${ro.zygote}.rc
。这个就是通过系统版本加载对应的init.zygote64.rc和init.zygote32.rc两个文件。
然后就会加载类app_main.cpp
,在app_main.cpp
的main函数里面可以看到去创建了Zygote进程。并且进程名字就叫zygote。
1 | static const char ZYGOTE_NICE_NAME[] = "zygote"; |
Zygote
创建子进程的方式是通过fork函数来创建,这里我们需要搞懂父进程和子进程的关系。
父进程&子进程
子进程拥有父进程的全部资源包括代码。那你可能要问了,那子进程从代码哪个地方开始执行?答案是。从fork那个位置开始执行,fork之前的代码子进程不会去执行,他只会执行fork这行代码下面的代码。fork会返回一个pid。这个pid=0代表这是一个子进程,pid<0代表子进程创建失败,pid>0代表是父进程。我们就是通过这个pid的值来判断某些功能让谁来做。这里你可能又有问题了,那父进程在fork之前创建的对象比如Student,那在子进程里面,这个在fork之前创建的对象,他的指向地址和父进程是一样的吗?答案告诉你,是一样的。你在子进程打印出的Student对象地址和父进程打印的Student地址是一样的。那我在给你提个问题,那既然一样,我在子进程修改Student.name值,那父进程里面在获取这个name的值,是子进程修改的值吗?答案是:不是的。子进程修改值不会影响到父进程。因为在子进程那个地址是一个虚拟地址,真正指向的物理地址并不是那个。
在我第一次看ZygoteInit.java
这个类的时候,我一直不明白为什么zygote进程能够一直存活,
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22public static void main(String[] argv) {
if (startSystemServer) {
Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);
if (r != null) {
r.run();
return;
}
}
caller = zygoteServer.runSelectLoop(abiList);
} catch (Throwable ex) {
Log.e(TAG, "System zygote died with fatal exception", ex);
throw ex;
} finally {
if (zygoteServer != null) {
zygoteServer.closeServerSocket();
}
}
if (caller != null) {
caller.run();
}
}
比如创建systemServer
进程的时候,当创建完成后,这个runable一定是不为null的。所以就会执行r.run方法。然后执行return。这里都return了。那为什么zygote进程还是活着的,不是应该死掉了吗。
来看下forkSystemServer
方法:
1 | private static Runnable forkSystemServer(String abiList, String socketName, |
哈哈你看懂了吗。我们可以看到里面执行了Zygote.forkSystemServer
方法去创建了子进程。然后当pid=0的时候去创建了Runbale对象,当pid不是0的时候,返回null。现在在回到ZygoteInit.java里面:
1
2
3
4
5
6
7
8
9public static void main(String[] argv) {
if (startSystemServer) {
Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);
if (r != null) {
r.run();
return;
}
}
}
可以看到当是主进程的时候,这个r是等于null的,所以主进程不会走进return。所以主进程这个时候也不会死。同理你可以去看runSelectLoop方法,他里面有个while的死循环,这就让这个zygote进程可以一直活着了。
想搞懂zygote进程不会死的原因,你一定要先搞懂父进程和子进程的原理和执行逻辑。