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)建的子進程會繼承父進程的所以資源失暂。如果調(diào)用了execve加載調(diào)用了另一個二進制程序鳄虱,繼承的父進程資源將被新啟動程序的資源替換掉凭峡。
3.信號處理-SIGCHLD
父進程fork出子進程,如果子進程異常中止了想罕,父進程就會收到一個SIGCHLD信號悠栓,重啟子進程按价。如:init進程fork出zygote進程,如果zygote進程異常中止了楼镐,init進程會接收到SIGCHLD信號,然后重啟zygote進程框产。
準備工作
Zygote進程啟動之后做了什么?
Zygote啟動之后秉宿,執(zhí)行了execve系統(tǒng)調(diào)用,這個系統(tǒng)調(diào)用執(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進程調(diào)用fork函數(shù),啟動SystemServer進程拾弃。
3.進入loop循環(huán)
接下來值桩,SystemServer會使用Socket與Loop循環(huán)進行通信豪椿。
Loop循環(huán)
在Loop循環(huán)中携栋。主要接收和處理Socket/MQ/Binder驅(qū)動等發(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機制敲茄。