本文是 Android 系統(tǒng)學(xué)習(xí)系列文章中的第一章節(jié),從大體上說明 Android 系統(tǒng)是如何啟動(dòng)的?從開機(jī)到程序啟動(dòng),發(fā)生了那些步驟,這些步驟意味著什么?歡迎進(jìn)入今天的「走進(jìn)科學(xué)」,逃 :)。對(duì)此系列感興趣的同學(xué),可以收藏這個(gè)鏈接 Android 系統(tǒng)學(xué)習(xí),也可以使用 RSS 進(jìn)行訂閱。
系統(tǒng)分區(qū)劃分
Android 達(dá)人都經(jīng)歷過刷機(jī)的體驗(yàn),如果通過 fastboot 來進(jìn)行刷機(jī)的話,會(huì)在刷機(jī)界面看到如下的幾個(gè)步驟。這些步驟是做什么用的?就是通過 fastboot 協(xié)議更新和燒錄到 Android 手機(jī)對(duì)應(yīng)的分區(qū)上。對(duì) fastboot 感興趣的同學(xué),可以點(diǎn)擊這個(gè) 鏈接 進(jìn)行查看。
fastboot flash boot boot.img
fastboot flash system system.img
fastboot flash userdata userdata.img
fastboot flash cache cache.img
fastboot flash recovery recovery.img
fastboot reboot
從 fastboot 的燒錄過程中可以看出 Android 系統(tǒng)的大致分區(qū),這里我也通過 adb shell 中的 df 命令查看了小米手機(jī)中的系統(tǒng)分區(qū),如下圖所示。

一般而言,雖然各個(gè)手機(jī)廠商在在系統(tǒng)上的實(shí)現(xiàn)不一致,Android 系統(tǒng)分為下面表格中的幾個(gè)部分。

| 分區(qū) | 功能 |
|---|---|
| boot | 系統(tǒng)引導(dǎo)分區(qū),包含著android 內(nèi)核,系統(tǒng)沒有這個(gè)無法啟動(dòng)。這一部分的鏡像在 boot unlocked 時(shí),也能夠被擦除,但在這個(gè)過程中,不能被打斷,關(guān)機(jī)等等,否者會(huì)導(dǎo)致系統(tǒng)無法啟動(dòng)。 |
| system | Android 整個(gè)系統(tǒng)所在地,也包含預(yù)裝的應(yīng)用(這是預(yù)裝的APP,手機(jī)廠商盈利的一種渠道), |
| recovery | 備份分區(qū),啟動(dòng)時(shí)可進(jìn)入 recovery ,然后在這個(gè)模式下進(jìn)行相應(yīng)的 recovery 操作。 |
| data | 應(yīng)用程序相關(guān)的數(shù)據(jù),例如你安裝的豌豆莢,數(shù)據(jù)就放在 /data/data/com.wandoujia.phoenix2 下面,當(dāng)進(jìn)行恢復(fù)出廠設(shè)置時(shí),這部分?jǐn)?shù)據(jù)會(huì)被擦除掉。 |
| cache | 用于存放緩存相關(guān)的數(shù)據(jù)。 |
| misc | 存放一些硬件配置、USB 配置等等信息,如果被擦除可能會(huì)導(dǎo)致某些系統(tǒng)設(shè)備無法正常工作。 |
Android 系統(tǒng)啟動(dòng)
如我們所知,Android 系統(tǒng)是基于 Linux 系統(tǒng)開發(fā)而成,在其中針對(duì)移動(dòng)設(shè)備的特性進(jìn)行了相應(yīng)的調(diào)整,所以 Android 系統(tǒng)大體上可以分為 Linux 內(nèi)核部分和 應(yīng)用系統(tǒng)部分。在 Android 系統(tǒng)啟動(dòng)的時(shí)候,也會(huì)先啟動(dòng) Linux 內(nèi)核,然后再啟動(dòng)應(yīng)用系統(tǒng)。整個(gè)啟動(dòng)步驟分為 6 個(gè)部分,在下面進(jìn)行詳細(xì)的描述。
啟動(dòng)電源以及系統(tǒng)啟動(dòng)
當(dāng)電源按下,引導(dǎo)芯片代碼開始從預(yù)定義的地方(固化在ROM)開始執(zhí)行。加載引導(dǎo)程序到RAM,然后執(zhí)行。
Boot Loader
Android系統(tǒng)是基于Linux操作系統(tǒng)的,所以它最初的啟動(dòng)過程跟Linux一樣。當(dāng)設(shè)備通電時(shí),首先執(zhí)行BootLoader引導(dǎo)裝載器,BootLoader是在操作系統(tǒng)內(nèi)核運(yùn)行之前運(yùn)行的一小段程序。BootLoader 的概念在各個(gè)操作系統(tǒng) windows, mac, Android 中都存在。通過這段小程序初始化硬件設(shè)置,建立內(nèi)存空間映射圖,從而將系統(tǒng)的軟硬件環(huán)境導(dǎo)入到合適的狀態(tài),以使為最終調(diào)用操作系統(tǒng)內(nèi)核準(zhǔn)備好正確的運(yùn)行環(huán)境。
BootLoader 在任何軟件之前執(zhí)行,因而也沒有類似于虛擬機(jī)那樣的概率來屏蔽不同運(yùn)行環(huán)境的差異,因而某個(gè)主板都有特定的BootLoader。另一方面,iOS 系統(tǒng)由于其各個(gè)版本間的穩(wěn)定性,因而不同版本件的 BootLoader 差異不大。另一方面,Android OS 是開源系統(tǒng),其可以運(yùn)行在不同的硬件上,這些硬件千差萬別,因而在 Android 上的 BootLoader 也各有不同。
一般而言 BootLoader 出于鎖閉狀態(tài),畢竟廠商開發(fā)出系統(tǒng)后,還是希望在 ROM 上的 Android 系統(tǒng)保持不變。因而刷機(jī)的第一步,往往是解鎖 BootLoader.
總結(jié)起來,BootLoader 完成的工作是:
- 初始化 RAM
- 初始化基礎(chǔ)硬件,例如 WIFI
- 加載內(nèi)核和內(nèi)存空間映射圖
- 跳轉(zhuǎn)到內(nèi)核中
內(nèi)核模塊
內(nèi)核模塊,負(fù)責(zé)了大部分的硬件、驅(qū)動(dòng)和文件系統(tǒng)的初始化,這部分都在內(nèi)核空間完成,不涉及用戶空間的內(nèi)容。內(nèi)核模塊的初始化是非常硬件相關(guān)的,目的就是使得 CPU 能夠更快地執(zhí)行 C 代碼,然后在這執(zhí)行完畢后,初始化各個(gè)子系統(tǒng),來執(zhí)行 init 進(jìn)程。
Init 進(jìn)程
Init 進(jìn)程作為第一個(gè)執(zhí)行的進(jìn)程,開天辟地。這個(gè)進(jìn)程主要做兩件事情,掛在相應(yīng)的目錄(/sys,/dev 等等),另一方面是執(zhí)行 init.rc 腳本,可通過 init.rc 源碼 查看相應(yīng)的鏈接。
Init 進(jìn)程會(huì)啟動(dòng) Runtime 運(yùn)行時(shí)服務(wù),所謂的 Runtime 服務(wù)就是將中間代碼靜態(tài)編譯成本地代碼。而 Android 所使用的 Java 動(dòng)態(tài)執(zhí)行,所依附的正式這個(gè) Runtime 環(huán)境。
其后,Init 進(jìn)程會(huì)啟動(dòng)一些本地守護(hù)進(jìn)程,這些守護(hù)進(jìn)程啟動(dòng)后,會(huì)初始化其相應(yīng)的模塊,在其中最特別的就是 Zygote。不過 Init 進(jìn)程不會(huì)直接啟動(dòng) Zygote 進(jìn)程,而是使用 app_process 命令來通過 Android Runtime 來啟動(dòng),Android Runtime 會(huì)啟動(dòng)第一個(gè) Davlik 虛擬機(jī),并調(diào)用 Zygote 的 main 方法。
Zygote and Dalvik
對(duì)于每一個(gè)運(yùn)行的程序,Android 都會(huì)賦予其單獨(dú)的虛擬機(jī),以支持其運(yùn)行,但每一次新建虛擬機(jī)的開銷都不小,那么如何來縮短這個(gè)時(shí)間了?尤其是針對(duì)嵌入式設(shè)備,都希望相應(yīng)速度能夠達(dá)到理想的狀況。Zyogte 就是用來解決這個(gè)問題的,其中文意思是受精卵。從這個(gè)名字上可以看出,其余的應(yīng)用進(jìn)程都是通過 fork 這個(gè)進(jìn)程來實(shí)現(xiàn)的,他們共享相同的內(nèi)存區(qū)域,這樣能減少不少的內(nèi)存占用開銷和應(yīng)用啟動(dòng)時(shí)間。
為了加速 App 的啟動(dòng),Zygote 進(jìn)程會(huì)預(yù)先加載 App 在運(yùn)行時(shí)所需的資源和 Class 文件到系統(tǒng) RAM 中。Zygote 會(huì)監(jiān)聽其 Socket (/dev/socket/zygote) 來判斷是否需要啟動(dòng) App。每當(dāng)監(jiān)聽到需要?jiǎng)?chuàng)建 App 的請(qǐng)求時(shí),就 fork 一個(gè)進(jìn)程即可。這樣的好處在于最初始的 Zygote 進(jìn)程,保有所有的系統(tǒng) Class 和 App 啟動(dòng)可能需要的資源,這樣一來,就不需要啟動(dòng)一個(gè) App 時(shí),動(dòng)態(tài)去加載相應(yīng)的資源。
監(jiān)聽 /dev/socket/zygote socket.
/**
* Registers a server socket for zygote command connections
*
* @throws RuntimeException when open fails
*/
private static void registerZygoteSocket(String socketName) {
if (sServerSocket == null) {
int fileDesc;
final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;
try {
String env = System.getenv(fullSocketName);
fileDesc = Integer.parseInt(env);
} catch (RuntimeException ex) {
throw new RuntimeException(fullSocketName + " unset or invalid", ex);
}
try {
sServerSocket = new LocalServerSocket(
createFileDescriptor(fileDesc));
} catch (IOException ex) {
throw new RuntimeException(
"Error binding to local socket '" + fileDesc + "'", ex);
}
}
}
為何在 Android 中 fork Zygote 進(jìn)程如此高效了?Linux Kernel 采用了 Copy-On-Write 的技術(shù),Copy-On-Write 的意思是只有在寫的時(shí)候才單獨(dú)復(fù)制一份,而讀的時(shí)候不進(jìn)行操作。 換而言之 fork zygote 實(shí)際上并未實(shí)際復(fù)制什么東西,只有在發(fā)生寫操作時(shí),才單獨(dú)復(fù)制一份。而另一方面,class 和 Resource 資源文件并不需要重新寫,這些文件在絕大多數(shù)時(shí)候都是只讀的。最后,實(shí)際的效果就是盡管運(yùn)行著多個(gè) APP,但實(shí)際只有一份 class 和 resource 文件在 Zygote 進(jìn)程中。
System Server 和 系統(tǒng)服務(wù)
絕大多數(shù) App 都是通過 fork Zygote 進(jìn)程來完成了,只有一個(gè)例外,那就是 System Sever。在啟動(dòng) System Server 之后,其他系統(tǒng)服務(wù)將自己注入到 System Server 中,同時(shí)其他系統(tǒng)服務(wù)也完成啟動(dòng)。這些服務(wù)主要包括,Power Manager,Telephony Registry,Battery Service,Window Manager等等。在這其中也包括我們熟知的 Activity Manager,Activity Manager在啟動(dòng)完成后,會(huì)發(fā)送一個(gè) Intent.CATEGORY_HOME 的 intent,從而我們就能看到我們熟知的桌面。

由于之前對(duì) System Server 進(jìn)行過詳細(xì)的講解,這里就不在贅述,感興趣的同學(xué)可以查看這篇文章 Android Binder 全解析(2) -- 設(shè)計(jì)詳解
總結(jié)
上述章節(jié)把 Android 啟動(dòng)中發(fā)生的事情表述完畢,現(xiàn)在沒有什么比下面這張圖更能總結(jié)觀點(diǎn)了。

參考文獻(xiàn)
文檔信息
- 版權(quán)聲明:自由轉(zhuǎn)載-非商用-非衍生-保持署名(創(chuàng)意共享3.0許可證)
- 發(fā)表日期: 2016年6月16日
- 社交媒體: weibo
- Feed訂閱:www.woaitqs.cc/feed.xml