對Zygote啟動流程的理解

Zygote的作用是什么?

Zygote主要作用有兩點:
1.啟動SystemServer。
2.孵化應用進程。
應用啟動時會將常用類、JNI函數(shù)、主題資源、共享庫等直接從Zygote繼承,避免每個應用進程都加載一邊相同的資源,達到資源共享提升性能的目的。

啟動流程

進程啟動

1.Linux系統(tǒng)啟動之后,用戶空間啟動第一個進程init進程,init進程會讀取init.rc文件,啟動init.rc文件中記錄的需要啟動的進程。Zygote就是需要啟動的進程之一。

啟動配置文件init.rc部分配置:

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 media
onrestart restart netd
writepid /dev/cpuset/foreground/tasks

2.進程是如何啟動的?
Linux啟動進程有兩種方式,第一種是fork+handle,第二種是fork+execve.這里使用fork+execve啟動進程。
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 
    //@path 可執(zhí)行程序的路徑
    //@argv 執(zhí)行程序的參數(shù)
    //@env 環(huán)境變量
    execve(path,argv,env);
}else{
    //parent process
}

fork函數(shù)會分別在父進程和子進程各返回一次,在子進程中返回的pid值為0,父進程中返回進程的pid,我們可以通過pid的值判斷是在父進程還是子進程中。
默認情況下,創(chuàng)建的子進程會繼承父進程的所以資源。如果調用了execve加載調用了另一個二進制程序,繼承的父進程資源將被新啟動程序的資源替換掉。
3.信號處理-SIGCHLD
父進程fork出子進程,如果子進程異常中止了,父進程就會收到一個SIGCHLD信號,重啟子進程。如:init進程fork出zygote進程,如果zygote進程異常中止了,init進程會接收到SIGCHLD信號,然后重啟zygote進程。

準備工作

Zygote進程啟動之后做了什么?
Zygote啟動之后,執(zhí)行了execve系統(tǒng)調用,這個系統(tǒng)調用執(zhí)行的是一個用C++編寫的二進制可執(zhí)行程序,做了一些準備工作后,Zygote就會切換到Java部分中運行。
-Zygote的Native部分
Zygote的Native部分主要有三個事情需要準備:
1.啟動android虛擬機
2.注冊Android的JNI函數(shù)
3.進入Java世界

int main(int argc,char *argv[]){
    JavaVM *jvm;
    JNIEnv *env;
    JNI_CreateJavaVM(&jvm,(void **)&env,&vm_args);
    jclass clazz = env->FindClass("ZygoteInit");
    jmethodID method = env-> GetStaticMethodId(clazz,"Main","([Ljava/lang/String;)V");
    env->CallStaticVoidMethod(clazz,method,args);
    jvm->DestroyJavaVM();
}

-Zygote的Java部分
1.Preload Resource
首先,zygote會預加載資源:常用類、JNI函數(shù)、主題資源、共享庫等。
2.fork SystemServer
然后,zygote進程調用fork函數(shù),啟動SystemServer進程。
3.進入loop循環(huán)
接下來,SystemServer會使用Socket與Loop循環(huán)進行通信。

Loop循環(huán)

在Loop循環(huán)中。主要接收和處理Socket/MQ/Binder驅動等發(fā)來的消息。Loop循環(huán)是如何處理請求的?

boolean runOnce(){
    String[] args = readArgumentList();
    int pid = Zygote.forkAndSpecialize();
    if(pid==0){
        //in child process
        handleChildProc(args,...);
        return true;
    }
}

在runOnce函數(shù)中,先讀取由AMS跨進程發(fā)送來的參數(shù)列表,然后根據(jù)參數(shù)fork出子進程,最后子進程中執(zhí)行ActivityThread.main();函數(shù)。

注意:
1.Zygote在fork時要保證是單線程的。父進程中有多少個線程,如守護線程和多個虛擬機,子進程在創(chuàng)建的時候只有一個線程,對于子進程來說,為防止線程安全問題,如資源搶占導致死鎖等情況,在fork時先暫停其他線程,fork進程結束后,再重啟恢復其他線程。
2.Zygote的IPC沒有采用Binder機制,而是采用了本地的socket。binder機制并不是從Zygote繼承而來,而是應用程序啟動之后,自己啟動的binder機制。

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內容