Zygote是由init进程启动的。
而在Android系统中,Dalvik/ART虚拟机、应用程序进程以及运行系统的关键服务的SystemServer进程都是由Zygote进程(孵化器)来创建的。
Zygote进程的启动过程
init进程启动Zygote时主要是调用app_main.cpp的main函数中的AppRuntime的start放来启动Zygote进程的。
来看frameworks/base/cmds/app_process/app_main.cpp
。
int main(int argc, char* const argv[])
{
//...
while (i < argc) {
const char* arg = argv[i++];
if (strcmp(arg, "--zygote") == 0) {
zygote = true; //如果当前运行在Zygote进程中,则设为true
niceName = ZYGOTE_NICE_NAME;
} else if (strcmp(arg, "--start-system-server") == 0) {
//如果当前运行在SystemServer进程中,则将startSystemServer设置为true
startSystemServer = true;
}
//...
}
//...
//如果运行在Zygote进程中
if (zygote) {
//启动ZygoteInit
runtime.start("com.android.internal.os.ZygoteInit", args, zygote); //启动Zygote进程
}
//...
}
Zygote进程都是通过fork自身来创建子进程的,这样Zygote进程以及它的子进程都可以进入app_main.cpp的main函数,所以main函数中会判断运行在哪个进程。
接着,来看frameworks/base/core/jni/AndroidRuntime.cpp#start()
这部分详见我的博客Android虚拟机的启动 源码分析
AndroidRuntime#start()函数会启动Java虚拟机,接着通过JNI调用ZygoteInit的main方法后,Zygote便进入了Java框架层,此前是没有任何代码进入Java框架层的,换句话说Zygote开创了Java框架层。
来看frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
public static void main(String argv[]) {
//...
//创建一个Server端的Socket,socketName的值为"zygote"
zygoteServer.registerServerSocket(socketName);
//...
//预加载资源
preload(bootTimingsTraceLog);
//...
if (startSystemServer) {
//启动SystemServer进程
Runnable r = forkSystemServer(abiList, socketName, zygoteServer);
}
//等待AMS请求
zygoteServer.closeServerSocket();
}
可以看到ZygoteInit的main方法主要做了4件事情
- 创建一个Server端的Socket
- 预加载类和资源
- 启动SystemServer进程
- 等待AMS请求创建新的应用程序进程
来看下registerServerSocket,这里创建了一个Server端的Socket,
然后,当启动SystemServer进程后,会执行ZygoteServer的runSelectLoop方法,无限轮询来等待ActivityManagerService请求Zygote来创建新的应用程序进程。
Runnable runSelectLoop(String abiList) {
//...
fds.add(mServerSocket.getFileDescriptor()); //将创建的服务器端Socket的fd字段添加到fds中
//...
//无限循环等待AMS的请求
while (true) {
StructPollfd[] pollFds = new StructPollfd[fds.size()];
for (int i = 0; i < pollFds.length; ++i) { //通过遍历将fds存储的信息转移到pollFds数组中
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) { //对pollFds进行遍历
if ((pollFds[i].revents & POLLIN) == 0) {
continue;
}
if (i == 0) { //如果i==0,说明服务器端Socket与客户端Socket连接上了 (Zygote进程与AMS建立了连接)
//通过acceptCommandPeer方法得到ZygoteConnection类
ZygoteConnection newPeer = acceptCommandPeer(abiList);
//添加到Socket连接列表peers中
peers.add(newPeer);
//将该ZygoteConnect的fd添加到fds中,以便可以接受到AMS发送过来的请求
fds.add(newPeer.getFileDesciptor());
} else { //如果i!=0,说明AMS像Zygote进程发送了一个创建应用进程的请求
//调用ZygoteConnection的runOnce函数来创建一个新的应用程序进程
boolean done = peers.get(i).runOnce(this);
if(done){
//将这个连接从Socket连接列表peers和fds中移除
peers.remove(i);
fds.remvoe(i);
}
}
}
}
}
Zygote的IPC没有采用binder,而是采用了Socket,binder机制是应用程序启动之后,自己创建的
Zygote进程启动小结
Zygote进程启动做了如下几件事:
- 创建AppRuntime并调用其start方法,启动Zygote进程
- 创建Java虚拟机并为Java虚拟机注册JNI方法
- 通过JNI调用ZygoteInit的main函数进入Zygote的Java层
- 通过
registerServerSocket()
创建服务器端Socket,并通过runSelectLoop方法等待AMS的请求来创建新的应用程序。 - 启动SystemServer进程