Zygote能夠說是Android開發面試很高頻的一道問題,但總有小夥伴在回答這道問題總不能讓面試滿意, 在這你就要搞清楚面試問你對Zygote的理解時,面試官最想聽到的和其實想問的應該是哪些?下面咱們經過如下幾點來剖析這道問題!java
下面來咱們來深刻剖析linux
Zygote的做用分爲兩點:android
關於這個問題答出了這兩點那就是OK了。可能大部分小夥伴可能能答出第二點,第一點就不是很清楚。SystemServer也是Zygote啓動的,由於SystemServer須要用到Zygote準備好的系統資源包括:ios
直接從Zygote繼承過來就不須要從新加載過來,那麼對性能將會有很大的提高。面試
在說Zygote啓動流程以前,先明確一個概念:啓動三段式,這個能夠理解爲Android中進程啓動的經常使用套路,分爲三步驟:架構
這裏要了解LOOP循環是什麼,其實LOOP做用是不停的接受消息
,處理消息
,消息的來源能夠是Soket
、MessageQueue
、Binder
驅動發過來的消息,但不管消息從哪裏來,它整個流程都是去接受消息,處理消息。這個啓動三段式,它不光是Zygote進程是這樣的,只要是有獨立進程的,好比說系統服務進程,本身的應用進程都是如此。app
Zygote進程的啓動取決於init進程,init進程是它是linux啓動以後用戶空間的第一個進程,下面看一下啓動流程:jvm
在init.rc 文件中會import /init.${ro.zygote}.rc,init.zygoteXX,XX指的是32或者64,對咱們沒差咱們直接看init.zygote32.rc便可。配置文件比較長,這裏作了截取保留了Zygot相關的部分。socket
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server class main socket zygote stream 660 root system onrestart write /sys/android_power/request_state wake onrestart write /sys/power/state on onrestart restart audioserver writepid /dev/cpuset/foreground/tasks
說完了啓動配置呢,這裏來聊一下啓動進程,啓動進程有兩種方式:函數
第一種:fork+handle
pid_t pid = fork(); if (pid == 0){ // child process } else { // parent process }
第二種:fork+execve
pid_t pid = fork(); if (pid == 0) { // child process execve(path, argv, env); } else { // parent process }
二者看起來差很少,首先首先都會調用fork函數建立子進程,這個函數比較奇特會返回兩次,子進程返回一次,父進程返回一次。區別在於:
當父進程fork子進程後,父進程須要關注這個信號。當子進程掛了,父進程就會收到SIGCHLD,這時候父進程就能夠作一些處理。例如Zygote進程若是掛了,那父進程init進程就會收到信號將Zygote進程重啓。
主要分爲兩部分Native層處理和Java層處理,Zygote進程啓動以後,它執行了execve系統調用,它執行的是用C++寫的二進制的可執行程序裏的main函數做爲入口,而後在Java層運行!
先來看一下Native層的處理流程
在app_main.cpp文件,AndroidRuntime.cpp文件。咱們能夠找到幾個主要函數名
int main(int argc,char *argv[]){ JavaVM *jvm; JNIEnv *env; JNI_CreateJavaVM(&jvm,(void**)&env,&vm_args); //建立Java虛擬機 jclass clazz = env->FindClass("ZygoteInit"); //找到叫ZygoteInit的Java類 jmethodID method = env->GetStaticMethodID(clazz,"Main","[Ljava/lang/String;)V"); //找到ZygoteInit類中的Main的靜態函數 env->CallStaticVoidMethod(clazz,method,args); //調用main函數 jvm->DestroyJavaVM(); }
根據上述代碼,你會發如今咱們的應用裏直接就能夠 JNI 調用了,並不須要建立虛擬機。由於應用進程是Zygote進程孵化出來的,繼承了父進程的擁有虛擬機,只須要重置數據便可。
接着看一下Java層的處理,具體可參考ZygoteInit文件的main方法
boolean runOnce() { String[] args = readArgumentList(); //讀取參數列表 int pid = Zygote.forkAndSpecialize(); //根據讀取到的參數啓動子進程 if(pid == 0) { //in child //執行ActivityThread的入口函數(main) handleChildProc(args,...); return true; } }
Zygote啓動流程中須要主要如下2點問題
若是你以爲這篇內容對你還蠻有幫助,我想邀請你幫我三個小忙: