Android Zygote進程啓動過程

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件事情

  1. 創建一個Server端的Socket
  2. 預加載類和資源
  3. 啓動SystemServer進程
  4. 等待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進程啓動做了如下幾件事:

  1. 創建AppRuntime並調用其start方法,啓動Zygote進程
  2. 創建Java虛擬機併爲Java虛擬機註冊JNI方法
  3. 通過JNI調用ZygoteInit的main函數進入Zygote的Java層
  4. 通過registerServerSocket()創建服務器端Socket,並通過runSelectLoop方法等待AMS的請求來創建新的應用程序。
  5. 啓動SystemServer進程
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章