前言
还是来看看,Zygote进程吧,这个和日常开发的关系还是很紧密的,我们今天对它的创建,启动和工作的方面对Zygote进程来梳理一下:
怎么理解Zygote
zygote,硬翻过来是受精卵的意思, 我们先大概的认识下:
- zygote进程是由init进程创建的;init管理zygote的生命周期;
- 系统中大部分应用进程是从zygote直接或者间接创建的;
- zygote进程在Android系统的全生命周期都是存活的,守护并管理这他的子孙;
基于上面的总体映像.我们到到代码中去看看:
代码梳理
1. 程序的起点
首先,我们在init.rc文件中看到,
import /init.${ro.zygote}.rc
看到上面,我们就可以猜到zygote也会和init进程一样有一个rc文件了,我们我们连接设备,在终端执行adb shell
.然后ls
,就会出现下图显示的文件(当然,这需要开发版本的设备才能看得到)
init程序在解析了自身的init.rc文件后,当处理到zygte的相关条目时,就会去启动zygote进程(这个过程就不在深入,):
我们先了zygote的rc文件是怎样子的:
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
class main
priority -20
user root
group root readproc reserved_disk
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
如上,对rc文件的语法和内容就不在具体深入,可参考system/core/rootdir/README.md
;
程序在读取到第一行的时候,就知道,接下来创建的程序有自己名称,独立运行代码路径,启动参数,
记下来我们就要去zygote的代码中一探究竟:
2.app_main
注意:当程序走到这个文件的时候,zygote所在的进程是已经创建好了,socket,近下来干的事情更像是zygote初始化.
老这样,我们先来到app_main.cpp文件的main()方法:
int main(int argc, char* const argv[])
{
std::string bootmode = GetProperty("ro.bootmode", "");
//这是高通平台的内容,我查看了aosp的代码,没有这块,这个我们就不去具体分析了,下面代码不关乎大的流程的小细节都略过
if ((strncmp(bootmode.c_str(), "ffbm-00", 7) == 0)
|| (strncmp(bootmode.c_str(), "ffbm-01", 7) == 0)) {
return 0;
}
...
// Parse runtime arguments. Stop at first unrecognized option.
// 这里就是在解析zygote的rc文件传的参数了,,我们看过rc文件,这里的参数也就很清楚是什么了;
// 所以下面的startSystemServer = true;zygote = true;
bool zygote = false;
bool startSystemServer = false;
bool application = false;
String8 niceName;
String8 className;
++i; // Skip unused "parent dir" argument.
while (i < argc) {
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;
}
}
...
// 说明接下来在zygote初始化好后,是需要创建systemServer进程的
if (startSystemServer) {
args.add(String8("start-system-server"));
}
...
// 现在runtime.需要到"com.android.internal.os.ZygoteInit"去继续运行,当期那的代码就算是走完了
if (zygote) {
runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
}
...
如上所示,从rc文件中的zygote的代码主要这些内容,然后就会调用runtime的start()函数继续执行,
2.1 appRuntime和AndroidRuntime
我们先看看这个runtime是个什么东西.runtime是AppRuntime的一个实例,AppRuntime类继承自AndroidRuntime;
frameworks/base/core/jni/include/android_runtime/AndroidRuntime.h
frameworks/base/core/jni/AndroidRuntime.cpp
- AndroidRuntime: 这里的代码就不贴出来了,我们可以认为AndroidRuntime这个类就是供创建VM(虚拟机),供Java和native之间相互调用的中介.因为其中有创建VM的函数
startVM()
,VM创建完成的回调函数onStarted(),onZygoteInit()
,Native层查找Java层的类以及调用java方法的函数findClass()和callMain()
,以及大量注册jni方法的数组RegJNIRec
等等 - AppRuntime我们又该怎么理解这个AppRuntime呢?因为AppRuntime是继承自AndroidRuntime,
并且其内部并主要还是重写了AndroidRuntime一些方法,那我们就将AppRuntime和AndroidRuntime同等看待.
2.2 AndroidRuntime.start()
本来是调用appRuntime的start()函数,appRuntime是继承AndroidRuntime,这里其实是调用AndroidRuntime.start()函数:
这就是我们的zygote升级的关键,要从native层跳到java层去了;要运行java,就得要依赖虚拟机毕竟Java语言与系统无关
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
//我们很清楚传进来的参数是什么(忘记了的话网上翻翻)
{
...
/* start the virtual machine */
//这个就注解就很好,我就不翻译了
JniInvocation jni_invocation;
jni_invocation.Init(NULL);
JNIEnv* env;
if (startVm(&mJavaVM, &env, zygote) != 0) {
return;
}
onVmCreated(env);
/*
* Register android functions.
*/
if (startReg(env) < 0) {
ALOGE("Unable to register all android natives\n");
return;
}
...
/*
* Start VM. This thread becomes the main thread of the VM, and will
* not return until the VM exits.
*/
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 {
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);
}
...
如上所示: start()函数内主要做了三件大事
- 创建VM
- 注册Native函数
- 查找Java类以及Java方法,然后跳转到Java层去执行,
说明:zygote初始化过程中创建VM, zygote创建应用进程的时候,应用进程就会获得zygote的资源,当然也有VM准确的说应该是克隆了zygote的所有资源
3. ZygoteInit
接下来我们就要从native层进入Java层了,首先我们看ZygoteInit:
frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
public static void main(String argv[]) {
// 一开始就new了个ZygoteServer类的实例,这个ZygoteServer是个socket服务端,
ZygoteServer zygoteServer = new ZygoteServer();
// Zygote goes into its own process group.
Os.setpgid(0, 0);
...
//注册用于zygote命令连接的socket的server,socket的fd在通过ANDROID_SOCKET_环境变量获取.
zygoteServer.registerServerSocketFromEnv(socketName);
// 预加载资源,常见类,共享库,文字图片资源等
preload(bootTimingsTraceLog);
...
// 访问安全设置
Zygote.nativeSecurityInit();
// Zygote process unmounts root storage spaces.
Zygote.nativeUnmountStorageOnInit();
...
//创建systemServer进程
Runnable r = forkSystemServer(abiList, socketName, zygoteServer);
// The select loop returns early in the child process after a fork and
// loops forever in the zygote.
caller = zygoteServer.runSelectLoop(abiList);
通过上面的主要方法的简述,我们就总体知道zygote在Java层做了那些事简单的终结就是
- 注册socket server端
- 预加载资源,这些资源的,zygote不一定会用,但是这个工作不白做,因为应用在被创建后可以直接拷贝zygote加载的这些资源,【哈哈,zygote就是这么好.为子孙尽心尽力】
- 然后创建systemServer进程,这是Android系统的很重要服务.
- 最后进入zygoteServer的成员runSelectLoop()方法.这就是进入了一个循环,会监听之前创建的socket有没有新的请求,主要是来自AMS的创建应用的请求.
4 总结
1.init进程在native层创建zygote进程,
2. 然后进zygote的初始化(创建VM.注册native方法,跳转Java层)
3.进入Java层,监听socket用于通信,预加载资源,
4. 最后进入lop循环,等待请求并处理