Android深水區(qū):Android系統(tǒng)啟動
開篇
對于Android系統(tǒng),有一張大家都見過的系統(tǒng)架構(gòu)圖

我們平時接觸的Android應(yīng)用開發(fā)及開源代碼都位于最上層(Application層),對Android FrameWork層接觸不多,但Android系統(tǒng)很多的精妙設(shè)計都處于FrameWork層及以下,要想理解Android系統(tǒng)則必須學(xué)習(xí)FrameWork層。本系列我將和大家一起開始FrameWork層的學(xué)習(xí),我們將依次學(xué)習(xí)Android啟動、Android跨進程Binder機制,Android四大組件啟動過程。在學(xué)習(xí)過程中不僅會接觸大量的Java層源碼,由于Android系統(tǒng)底層是linux,因此學(xué)習(xí)過程中還會涉及一些linux知識及C++代碼,為了不讓大家陷入代碼、糾于細節(jié),本系列主要會從架構(gòu)層面解釋具體原理,對應(yīng)節(jié)點會列出對應(yīng)源碼位置,有興趣的同學(xué)可以去進一步閱讀源碼。要想學(xué)好Android,只有那句程序猿至理名言RTFSC(Read The Fucking Source Code)。
關(guān)于Android源碼閱讀,推薦一個非常好的在線閱讀源碼閱讀網(wǎng)址:Android源碼
Android系統(tǒng)啟動流程
本文主要介紹Android系統(tǒng)的啟動過程,主要目的一是讓大家大致了解Android手機啟動后都在做什么,二是介紹幾個核心的系統(tǒng)服務(wù)及進程,為后續(xù)文章做一個鋪墊。本文以Android 9.0.0_r8系統(tǒng)源碼為例,Android系統(tǒng)啟動大致可以分為四步:
- 系統(tǒng)環(huán)境準備
- 啟動init進程
- 啟動Zygote進程
- 啟動SystemServer進程

下面我們依次來分析每一步都在做什么
系統(tǒng)環(huán)境準備
該步驟主要是用戶按下開機鍵后的一些硬件初始化、系統(tǒng)加載過程,簡單介紹不作過多說明
BootLoader
Bootloader是嵌入式系統(tǒng)在加電后執(zhí)行的第一段代碼,進行硬件初始化,獲取內(nèi)存大小信息等,調(diào)整手機到適配狀態(tài)。在它完成CPU和相關(guān)硬件的初始化之后,再將操作系統(tǒng)映像或固化的嵌入式應(yīng)用程序加載到內(nèi)存中然后跳轉(zhuǎn)到操作系統(tǒng)所在的空間,最終目標是拉起操作系統(tǒng)。當用戶按下開機鍵后,芯片就會開始將BootLoader加載到內(nèi)存中。
系統(tǒng)加載
BootLoader加載成功后,手機會通過BootLoader加載系統(tǒng),啟動系統(tǒng)內(nèi)核(Kernel)并做相應(yīng)的環(huán)境初始化設(shè)置,開始init進程啟動
init進程
init進程簡介
- 我們知道,Android系統(tǒng)也有很多自己的系統(tǒng)級的服務(wù)進程,Android系統(tǒng)可以正常運行都依賴于這些進程,而init進程是這些所有的進程的根進程,這些進程都是由init進程孵化而來。
- init進程是Android系統(tǒng)的第一個進程,我們可以通過
adb shell -p命令 看到,init進程的pid為1。
init啟動流程分析
init是處于linux系統(tǒng)的用戶空間,在第一步系統(tǒng)環(huán)境準備后,linux內(nèi)核啟動成功便會調(diào)用/system/core/init/Init.cpp 中的main()開始init進程的啟動。init.cpp中main()函數(shù)較長,做相應(yīng)截取說明
int main(int argc, char** argv) {
...
// 1、創(chuàng)建、掛載相應(yīng)文件
// Get the basic filesystem setup we need put together in the initramdisk
// on / and then we'll let the rc file figure out the rest.
mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755");
mkdir("/dev/pts", 0755);
...
// 2.初始化log服務(wù)、屬性服務(wù)
InitKernelLogging(argv);
....
property_init();
...
// 3、解析init.rc
LoadBootScripts(am, sm);
...
// 相關(guān)邏輯執(zhí)行完后,會進入一個while true循環(huán)等待任務(wù)執(zhí)行
}
代碼很長,我們關(guān)心的主要包含3步
第一步 創(chuàng)建、掛載相應(yīng)文件
- 創(chuàng)建并掛載系統(tǒng)運行時所需的目錄,主要包括tmpfs、devpts、proc、sysfs和selinuxfs五種文件系統(tǒng)。
第二步 初始化log服務(wù)、屬性服務(wù)
- 調(diào)用
InitKernelLogging(argv)初始化日志系統(tǒng),之后會執(zhí)行LOG(INFO) << "init first stage started!",出內(nèi)核中第一句log。 - 在Android系統(tǒng)中,所有的進程共享系統(tǒng)初始值,這些值存在于系統(tǒng)的共享內(nèi)存區(qū)域,通過調(diào)用
property_init()對相關(guān)值進行初始化。
第三步 解析init.rc配置文件
- LoadBootScripts函數(shù)主要工作就是解析init.rc文件,關(guān)鍵代碼
parser.ParseConfig("/init.rc") - init.rc文件是一個非常重要的配置文件,它由AIL語言(Android Init Language)編寫,源碼位于
/system/core/rootdir/init.rc,核心代碼如下。
# Now we can start zygote for devices with file based encryption
trigger zygote-start
-
trigger zygote-start從源碼注釋可以看出,這步開始初始化Zygote進程。
Zygote進程
Zygote進程簡介
Zygote是受精卵的意思,它是Android中的一個非常重要的守護進程服務(wù)(Daem Service),所有的其他Dalvik虛擬機(進程)都是通過zygote孵化(fork)出來的。Android應(yīng)用程序是由Java語言編寫的,運行在各自獨立的Dalvik虛擬機(進程)中。如果每個應(yīng)用程序在啟動之時都需要單獨運行和初始化一個虛擬機(進程),會大大降低系統(tǒng)性能,因此Android首先創(chuàng)建一個zygote虛擬機(進程),然后通過它孵化出其他的虛擬機(進程),進而共享虛擬機內(nèi)存和框架層資源,這樣大幅度提高應(yīng)用程序的啟動和運行速度。
Zygote是Android中最重要的一個進程,和Init進程,SystemServer進程是支撐Android世界的三極。Android8.0后對zygote.rc文件進行了拆分,存在以下四種:
- init.zygote32.rc
- init.zygote32_64.rc
- init.zygote64.rc
- init.zygote64_32.rc
我們以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
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart audioserver
onrestart restart cameraserver
onrestart restart media
onrestart restart netd
onrestart restart wificond
writepid /dev/cpuset/foreground/tasks
代碼不多,共15行,也是Android Init Language語法,執(zhí)行邏輯就是啟動進程,名稱為zygote,執(zhí)行程序為/system/bin/app_process,類名為main,當Zygote進程重啟時,重啟audioserver、cameraserver、media等進程。下面我們通過frameworks/base/cmds/app_process/app_main.cpp具體分析Zygote進程初始化流程。
Zygote啟動流程分析
Zygote進程初始化過程會進入Java層,因此我們分為C++層跟Java層分別分析。
C++層
同樣,我們看下app_main.cpp中的main方法,代碼較長,我們截取分析。
int main(int argc, char* const argv[])
{
...
// 1、創(chuàng)建AppRuntime變量
AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv)); // 1
// Process command line arguments
// ignore argv[0]
argc--;
argv++;
...
// 2、創(chuàng)建Zygote進程
while (i < argc) {
const char* arg = argv[i++];
if (strcmp(arg, "--zygote") == 0) {
// Zygote進程自己
zygote = true;
niceName = ZYGOTE_NICE_NAME;
} else if (strcmp(arg, "--start-system-server") == 0) {
// SystemServer進程
startSystemServer = true;
} else if (strcmp(arg, "--application") == 0) {
// 普通應(yīng)用進程
application = true;
}
...
}
...
if (zygote) {
runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
} else if (className) {
runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
} else {
fprintf(stderr, "Error: no class name or --zygote supplied.\n");
app_usage();
LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
}
}
第一步 創(chuàng)建AppRuntime變量
- 定義了一個名為runtime的變量,其類型是AppRuntime,該類繼承自AndroidRuntime,也定義在app_main.cpp中
第二步 創(chuàng)建Zygote進程,進入Java層
- 定義了一個名為runtime的變量,其類型是AppRuntime,該類繼承自AndroidRuntime,也定義在app_main.cpp中
- Zygote進程都是通過fork自身來創(chuàng)建子進程的,這樣Zygote進程以及它的子進程都可以進入app_main.cpp的main()函數(shù),因此main()函數(shù)中為了區(qū)分當前運行在哪個進程,會判斷參數(shù)argv中是否包含--zygote,若包含則說明main()函數(shù)是運行在Zygote進程中的并將變量zygote設(shè)置為true;判斷參數(shù)argv是否包含--start-system-server,若包含則說明main()函數(shù)是運行在SystemServer進程中的并在將變量startSystemServer設(shè)置為true;判斷參數(shù)argv是否包含--application,若包含則說明main()函數(shù)是運行在普通進程。
- 若zygote屬性為true,則通過AppRuntime的start()函數(shù),通過jni調(diào)用,執(zhí)行
com.android.internal.os.ZygoteInit中的main()方法,經(jīng)過此步,Android初始化首次進入Java層。下面我們開始研究ZygoteInit,該類位于/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
Java層
我們截取看下ZygoteInit中的main方法
// 1、創(chuàng)建Socket
...
String socketName = "zygote";
...
zygoteServer.registerServerSocketFromEnv(socketName);
...
// 2、預(yù)加載類、資源
preload(bootTimingsTraceLog);
...
// 3、fork SystemServer進程
if (startSystemServer) {
Runnable r = forkSystemServer(abiList, socketName, zygoteServer);
...
if (r != null) {
r.run();
return;
}
}
...
// 4、等待AMS消息
// The select loop returns early in the child process after a fork and
// loops forever in the zygote.
caller = zygoteServer.runSelectLoop(abiList);
第一步 創(chuàng)建Socket
- 調(diào)用
registerServerSocketFromEnv()方法創(chuàng)建一個Server端名為“zygote”的Socket,這個Socket用于與AMS(ActivityManagerService)通信,后續(xù)程序運行時若要創(chuàng)建普通進程,則由AMS通過該Socket通知Zygote進程孵化。這里稍微了解Android跨進程通信的可能會問,此處為什么不使用Binder進行跨進程通信,原因在于Binder機制依賴于ServiceManger,而此時ServiceManger還未創(chuàng)建。
第二步 預(yù)加載類、資源
- 調(diào)用
preload(bootTimingsTraceLog)方法,預(yù)加載類和資源,應(yīng)用程序中以com.android.internal.R.xxx頭的資源,便是此時由Zygote加載到內(nèi)存的。
第三步 fork SystemServer進程
- 在C++層第二步中判斷邏輯一致,當若傳入的參數(shù)中包含--start-system-server,則startSystemServer為true
- 調(diào)用
forkSystemServer()方法fork出SystemServer進程,調(diào)用run()方法啟動。
第四步
- 調(diào)用
ZygoteServer的runSelectLoop()方法,等待AMS請求創(chuàng)建新的應(yīng)用程序進程。
SystemServer進程
SystemServer進程簡介
- SystemServer進程是Zygote創(chuàng)建的第一個Java進程,主要用于創(chuàng)建系統(tǒng)服務(wù),ActivityMangerService、PackageManagerService和WindowManagerService等這些重要的服務(wù)都是通過SystemServer進程啟動的。
SystemServer啟動流程分析
上文談到forkSystemServer()方法,該方法進行一系列調(diào)用后,最終啟動SystemServer進程會進入com.android.server.SystemServer.java,該類的main方法直接調(diào)用SystemServer的run()方法,我們直接看run方法。
private void run() {
...
// 創(chuàng)建主線程
Looper.prepareMainLooper();
...
// 1、加載動態(tài)庫
System.loadLibrary("android_servers");
...
// 創(chuàng)建system Context
createSystemContext();
...
// 2、創(chuàng)建ServiceManager
mSystemServiceManager = new SystemServiceManager(mSystemContext);
...
// 3、啟動引導(dǎo)服務(wù)、啟動核心服務(wù)、啟動其他服務(wù)
startBootstrapServices();
startCoreServices();
startOtherServices();
...
}
第一步 加載動態(tài)庫
- 加載動態(tài)庫libandroid_servers.so,初始化native服務(wù)。
第二步 創(chuàng)建ServiceManager
- 創(chuàng)建SystemServiceManager對象,Binder機制啟用。
第三步 啟動引導(dǎo)服務(wù)、啟動核心服務(wù)、啟動其他服務(wù)
- 官方把系統(tǒng)服務(wù)分為了三種類型,分別是引導(dǎo)服務(wù)、核心服務(wù)和其他服務(wù)。
- 引導(dǎo)服務(wù)主要包括ActivityManagerService、PowerManagerService、PackageManagerService。
- 核心服務(wù)有DropBoxManagerService、BatteryService等。
- 其他服務(wù)是一些不緊要和不需要立即啟動的服務(wù),不一一舉例。
總結(jié)
至此,Android系統(tǒng)啟動核心部分已經(jīng)分析結(jié)束。我們分析了Android系統(tǒng)啟動后硬件環(huán)境準備,init進程如何啟動Zygote進程,Zygote進程如何孵化SystemServer進程。本文分析主要是流程分析,源碼分析只是指出關(guān)鍵方法,很多代碼細節(jié)一筆帶過,有興趣的同學(xué)可以自己去源碼內(nèi)研究。