一 概述
上一篇文章分析了 init 进程的整个启动流程。init 进程启动后,会解析 rc 文件,然后启动很多进程,其中很重要的一个进程就是 zygote 进程,zygote 进程又称受精卵进程, 所对应的可执行程序为 app_process,所对应的源文件是 app_main.cpp,进程名为 zygote,zygote 是 Android 系统创建的第一个 java 进程,它是所有 java 进程的父进程,zygote 进程最大意义是作为一个 Socket 的 Server 端,接收着来自四面八方的其它进程发出的进程创建请求,Android 中所有的应用进程的创建都是由一个应用进程通过 Binder 发送请求给 SystemServer 进程,SystemServer 进程再发送 Socket 消息给 zygote 进程,统一由 zygote 进程创建出来的。典型的 C/S 架构.下图为 zygote 进程在系统中的地位,其中图中红色标注为 Binder 通信方式,蓝色标注为 Socket 通信方式.
话说为什么 Android 系统采用这种架构呢,为什么所有进程的创建都是由 zygote 来做呢?原因有如下两点:
- zygote 进程在启动的时候会创建一个虚拟机实例,因此通过 zygote 这个父进程,创建的子进程都会继承这个虚拟机实例,app 中的 java 代码可以得到翻译执行。
- 进程与进程之间需要跨进程通信,由 zygote 进程作为父进程还可以获得一个 Binder 线程池,这样进程之间就可以使用 Binder 进行跨进程通信了。
基于以上两点,可以理解 zygote 进程为什么是所有应用进程的父进程的原因.
涉及到的源码路徑
/system/core/rootdir/init.rc
/system/core/init/main.cpp
/system/core/init/init.cpp
/system/core/rootdir/init.zygote64_32.rc
/frameworks/base/cmds/app_process/app_main.cpp
/frameworks/base/core/jni/AndroidRuntime.cpp
/libnativehelper/JniInvocation.cpp
/frameworks/base/core/java/com/android/internal/os/Zygote.java
/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
/frameworks/base/core/java/com/android/internal/os/ZygoteServer.java
/frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java
/frameworks/base/core/java/com/android/internal/os/RuntimeInit.java
/frameworks/base/core/java/android/net/LocalServerSocket.java
/system/core/libutils/Threads.cpp
二 zygote是如何被启动的
我们知道 init 进程启动后,会解析 init.rc 文件,然后创建和加载 service 字段指定的进程。zygote 进程就是以这种方式,被 init 进程加载并启动的。在 /system/core/rootdir/init.rc 中,通过如下引用来 load zygote 的 rc:
import /init.${
ro.zygote}.rc
其中 ${ro.zygote} 由各个厂家使用,现在的主流厂家基本使用 zygote64_32,因此,我们的 rc 文件为 init.zygote64_32.rc,我们来看这个文件:
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
socket zygote stream 660 root system
onrestart write /sys/android_power/request_state wake
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
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
socket zygote_secondary stream 660 root system
onrestart restart zygote
writepid /dev/cpuset/foreground/tasks
从这个 rc 文件中可以看到启动了二个进程,分别为 zygote 和 zygote_secondary,启动路徑为 /system/bin/app_process64 和 /system/bin/app_process32,对应的代码入口为:frameworks/base/cmds/app_process/app_main.cpp
三 zygote启动流程
3.1 zygote启动时序图
- init 进程通过解析 init.zygote64_32.rc 来启动位于 /system/bin/app_process64 的 zygote 进程,入口为 app_main.cpp
- 调用 AndroidRuntime 的 startVM() 方法创建虚拟机,再调用 startReg() 注册 JNI 函数
- 通过 JNI 方式调用 ZygoteInit.main(),第一次进入 Java 世界
- registerZygoteSocket() 建立 socket 通道,zygote 作为通信的服务端,用于响应客户端请求
- preload() 预加载通用类、drawable 和 color 资源、openGL 以及共享库以及 WebView,用于提高 app 启动效率
- zygote 完成大部分工作,接下来再通过 startSystemServer(),fork system_server 进程,它同时也是上层 framework 框架的运行载体
- zygote 任务完成,调用 runSelectLoop(),随时待命,当接收到创建新进程的请求时,立即唤醒并执行相应工作
3.2 zygote入口函数main
先来一张 zygote 在 native C 世界的代码调用图,如下:
frameworks/base/cmds/app_process/app_main.cpp
int main(int argc, char* const argv[])
{
//zygote传入的参数argv为“-Xzygote /system/bin --zygote --start-system-server --socket-name=zygote”
//zygote_secondary传入的参数argv为“-Xzygote /system/bin --zygote --socket-name=zygote_secondary”
AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
........
while (i < argc) {
const char* arg = argv[i++];
if (strcmp(arg, "--zygote") == 0) {
zygote = true;
//对于64位系统nice_name为zygote64; 32位系统为zygote
niceName = ZYGOTE_NICE_NAME;
} else if (strcmp(arg, "--start-system-server") == 0) {
//是否需要启动system server
startSystemServer = true;
} else if (strcmp(arg, "--application") == 0) {
//启动进入独立的程序模式
application = true;
} else if (strncmp(arg, "--nice-name=", 12) == 0) {
//niceName 为当前进程别名,区别abi型号
niceName.setTo(arg + 12);
} else if (strncmp(arg, "--", 2) != 0) {
className.setTo(arg);
break;
} else {
--i;
break;
}
}
........
if (!className.isEmpty()) {
//className不为空,说明是application启动模式
........
} else {
//进入zygote模式,新建Dalvik的缓存目录:/data/dalvik-cache
maybeCreateDalvikCache();
if (startSystemServer) {
//加入start-system-server参数
args.add(String8("start-system-server"));
}
String8 abiFlag("--abi-list=");
abiFlag.append(prop);
args.add(abiFlag); //加入--abi-list=参数
// In zygote mode, pass all remaining arguments to the zygote
// main() method.
for (; i < argc; ++i) {
//将剩下的参数加入args
args.add(String8(argv[i]));
}
}
........
if (!niceName.isEmpty()) {
//设置一个“好听的昵称” zygote\zygote64,之前的名称是app_process
runtime.setArgv0(niceName.string(), true /* setProcName */);
}
if (zygote) {
//如果是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 {
//没有指定类名或zygote,参数错误
fprintf(stderr, "Error: no class name or --zygote supplied.\n");
app_usage();
LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
}
}
zygote 本身是一个 Native 的应用程序,刚开始的进程名称为“app_process”,运行过程中,通过调用 setArgv0 将名字改为 zygote 或者 zygote64 (根据操作系统而来),最后通过 runtime 的 start() 方法来真正的加载虚拟机并进入 java 世界。
3.3 AndroidRuntime.start
frameworks/base/core/jni/AndroidRuntime.cpp
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
ALOGD(">>>>>> START %s uid %d <<<<<<\n",
className != NULL ? className : "(unknown)", getuid());
........
JniInvocation jni_invocation;
jni_invocation.Init(NULL);
JNIEnv* env;
//虚拟机创建,主要是关于虚拟机参数的设置
if (startVm(&mJavaVM, &env, zygote, primary_zygote) != 0) {
return;
}
........
// 注册JNI方法
if (startReg(env) < 0) {
ALOGE("Unable to register all android natives\n");
return;