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進程