5張圖搞懂Android系統(tǒng)啟動的核心流程~
大綱:
- Zygote啟動
- SystemServer啟動
- Launcher啟動
- 總結
- 細節(jié)補充
- 參考資料
本文約1.9k字,閱讀大約8分鐘庐镐。
Android源碼基于8.0莫湘。
init進程
是Linux內核啟動完成后在用戶空間啟動的第一個進程,主要負責初始化工作粗合、啟動屬性服務萍嬉、解析init.rc文件并啟動Zygote進程。
Zygote進程
是一個進程孵化器隙疚,負責創(chuàng)建虛擬機實例壤追、應用程序進程、系統(tǒng)服務進程SystemServer供屉。他通過fork(復制進程)的方式創(chuàng)建子進程行冰,子進程能繼承父進程的系統(tǒng)資源如常用類溺蕉、注冊的JNI函數、主題資源悼做、共享庫等疯特。
由于Zygote進程啟動時會創(chuàng)建虛擬機實例,由Zygote fork出的應用程序進程和SystemServer進程則可以在內部獲取到一個虛擬機實例副本肛走。
Zygote啟動
init進程會解析配置文件init.rc漓雅,來啟動一些需要在開機時就啟動的系統(tǒng)進程,如Zygote進程朽色、ServiceManager進程等邻吞。
init.rc是由Android初始化語言編寫的腳本配置。由于Android 5.0開始支持了64bit程序葫男,在init.rc里改成了通過${ro.zygote}
的值來引入Zygote相關的配置抱冷,
//system/core/rootdir/init.rc
import /init.${ro.zygote}.rc
${ro.zygote}
的取值有4種,在init.rc的同級目錄/system/core/rootdir下梢褐,可以看到4個Zygote相關的配置文件旺遮,表示系統(tǒng)所支持程序的bit位數,
- init.zygote32.rc利职,Zygote進程的執(zhí)行程序路徑為/system/bin/app_process
- init.zygote64.rc趣效,Zygote進程的執(zhí)行程序路徑為/system/bin/app_process64
- init.zygote32_64.rc,會啟動兩個Zygote進程猪贪,有兩個執(zhí)行程序跷敬,32為主模式
- init.zygote64_32.rc,會啟動兩個Zygote進程热押,有兩個執(zhí)行程序西傀,64為主模式
我們看到init.zygote32.rc文件,
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
class main
priority -20
user root
group root readproc reserved_disk
socket zygote stream 660 root system
...
第一行中桶癣,service
表示Zygote進程以服務的形式來啟動拥褂,zygote
則是進程的名字,/system/bin/app_process
是執(zhí)行程序的路徑牙寞,后面幾項則是傳給執(zhí)行程序的參數扫步,其中--start-system-server
表示在Zygote進程啟動后需要啟動SystemServer進程。
然后是最后一行幸缕,Zygote進程是使用socket來進行跨進程通信的涵亏,所以會創(chuàng)建一個名為zygote的socket,660表示訪問權限rw-rw----
惹挟,表示文件擁有者和同一群組用戶具有讀寫權限茄螃。
init進程啟動后,通過fork和execve來啟動Zygote進程连锯,
//system/core/init/service.cpp
bool Service::Start() {
//fork出子進程
pid = fork();
if (pid == 0) {//子進程會返回0归苍,父進程會返回子進程的pid
//strs[0]是執(zhí)行程序的路徑用狱,即execve會運行app_process
if (execve(strs[0], (char**) &strs[0], (char**) ENV) < 0) {
}
}
}
運行執(zhí)行程序app_process的入口函數main,
//frameworks/base/cmds/app_process/app_main.cpp
int main(int argc, char* const argv[]){
if (zygote) {
//啟動Zygote拼弃,進入ZygoteInit.main函數
runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
}
}
至此Zygote就正式啟動了夏伊。
綜上,init進程讀取配置文件init.rc后肴敛,fork出Zygote進程署海,通過execve函數執(zhí)行Zygote的執(zhí)行程序app_process,進入ZygoteInit類的main函數医男。
下面詳細分析app_main和ZygoteInit砸狞。
native層app_main
前邊可知app_main.cpp的main函數會調用runtime.start(),
//frameworks/base/core/jni/AndroidRuntime.cpp
void AndroidRuntime::start(...){
//1. 啟動java虛擬機
if (startVm(&mJavaVM, &env, zygote) != 0) {
return;
}
//2. 為java虛擬機注冊JNI方法
if (startReg(env) < 0) {
return;
}
//根據傳入的參數找到ZygoteInit類和他的main函數
//3. 通過JNI調用ZygoteInit的main函數
env->CallStaticVoidMethod(startClass, startMeth, strArray);
}
Java層ZygoteInit
來到ZygoteInit的main函數镀梭,
//ZygoteInit.java
public static void main(String argv[]) {
//是否要創(chuàng)建SystemServer
boolean startSystemServer = false;
//默認的socket名字
String socketName = "zygote";
//是否要延遲資源的預加載
boolean enableLazyPreload = false;
for (int i = 1; i < argv.length; i++) {
if ("start-system-server".equals(argv[i])) {
//在init.rc文件中刀森,有--start-system-server參數,表示要創(chuàng)建SystemServer
startSystemServer = true;
} else if ("--enable-lazy-preload".equals(argv[i])) {
//init.rc沒有這個參數报账,資源的預加載不會被延遲
enableLazyPreload = true;
} else if (argv[i].startsWith(SOCKET_NAME_ARG)) {
//init.rc可以通過--socket-name=指定socket名字來覆蓋默認值
socketName = argv[i].substring(SOCKET_NAME_ARG.length());
}
}
//1. 創(chuàng)建服務端socket研底,名字為socketName即zygote
zygoteServer.registerServerSocket(socketName);
if (!enableLazyPreload) {
//2. 沒有被延遲,就預加載資源
preload(bootTimingsTraceLog);
}
if (startSystemServer) {
//3. fork并啟動SystemServer進程
startSystemServer(abiList, socketName, zygoteServer);
}
//4. 等待AMS請求(AMS會通過socket請求Zygote來創(chuàng)建應用程序進程)
zygoteServer.runSelectLoop(abiList);
}
總結一下native層的3個環(huán)節(jié)和Java層的4個環(huán)節(jié):
SystemServer啟動
SystemServer
進程主要負責創(chuàng)建啟動系統(tǒng)服務如AMS透罢、WMS和PMS等榜晦。
從前邊可知SystemServer進程由Zygote進程fork出來并啟動,在ZygoteInit類中羽圃,
//ZygoteInit.java
private static boolean startSystemServer(...){
String args[] = {
//...
//啟動的類名:
"com.android.server.SystemServer",
};
//fork進程乾胶,由native層實現(xiàn)
pid = Zygote.forkSystemServer();
//處理SystemServer進程
handleSystemServerProcess(parsedArgs);
}
private static void handleSystemServerProcess(...){
ZygoteInit.zygoteInit(...);
}
public static final void zygoteInit(...){
//啟動binder線程池
ZygoteInit.nativeZygoteInit();
//內部經過層層調用,找到"com.android.server.SystemServer"類和他的main函數朽寞,然后執(zhí)行
RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
}
這里啟動了binder線程池识窿,SystemServer進程就可以用binder機制來跨進程通信了(Zygote進程是用socket來通信的),接著進入了SystemServer的main函數脑融,
//SystemServer.java
public static void main(String[] args) {
new SystemServer().run();
}
private void run() {
//創(chuàng)建looper
Looper.prepareMainLooper();
//加載動態(tài)庫libandroid_servers.so
System.loadLibrary("android_servers");
//創(chuàng)建系統(tǒng)上下文
createSystemContext();
//創(chuàng)建SSM喻频,用于服務的創(chuàng)建、啟動和生命周期管理
mSystemServiceManager = new SystemServiceManager(mSystemContext);
//服務根據優(yōu)先級被分成3批來啟動:
//啟動引導服務肘迎,如AMS甥温、PMS等
startBootstrapServices();
//啟動核心服務
startCoreServices();
//啟動其他服務
startOtherServices();
//開啟looper循環(huán)
Looper.loop();
}
看下AMS的啟動,
//SystemServer.java
private void startBootstrapServices() {
//由SSM創(chuàng)建啟動
mActivityManagerService = mSystemServiceManager.startService(
ActivityManagerService.Lifecycle.class).getService();
mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
}
private void startOtherServices() {
//AMS準備就緒
mActivityManagerService.systemReady(...);
}
總結一下妓布,SystemServer進程被創(chuàng)建后窿侈,主要做了3件事情:啟動binder線程池、創(chuàng)建SystemServiceManager(SSM)秋茫、用SSM啟動各種服務。
Launcher的啟動
Launcher
作為Android的桌面乃秀,用于管理應用圖標和桌面組件肛著。
前邊可知SystemServer進程會啟動各種服務圆兵,其中PackageManagerService啟動后會將系統(tǒng)中的應用程序安裝完成,然后由AMS來啟動Launcher枢贿。
//SystemServer.java
private void startOtherServices() {
//AMS準備就緒
mActivityManagerService.systemReady(...);
}
//ActivityManagerService.java
public void systemReady(...) {
//經過層層調用來到startHomeActivityLocked
}
boolean startHomeActivityLocked(...) {
//最終會啟動Launcher應用的Activity
mActivityStarter.startHomeActivityLocked(...);
}
Activity類是Launcher.java,剩下的流程就是加載已安裝的應用程序信息局荚,然后展示超凳,就不具體分析了。
總結
Android系統(tǒng)啟動的核心流程如下:
- Linux內核啟動
- init進程啟動
- init進程fork出Zygote進程
- Zygote進程fork出SystemServer進程
- SystemServer進程啟動各項服務(PMS耀态、AMS等)
- AMS服務啟動Launcher桌面
Zygote進程啟動好服務端socket后轮傍,便會等待AMS的socket請求,來創(chuàng)建應用程序進程首装。
細節(jié)補充
- Zygote的跨進程通信沒有使用binder创夜,而是socket,所以應用程序進程的binder機制不是繼承而來仙逻,而是進程創(chuàng)建后自己啟動的驰吓。
- Zygote跨進程通信之所以用socket而不是binder,是因為binder通信是多線程的系奉,而Zygote需要在單線程狀態(tài)下fork子進程來避免死鎖問題檬贰。
- PMS、AMS等系統(tǒng)服務啟動后會調用ServiceManager.addService()注冊缺亮,然后運行在自己的工作線程翁涤。
參考資料
- 書籍 - Android進階解密
- csdn - 為什么SystemServer進程與Zygote進程通訊采用Socket而不是Binder