Android面試必備:System、App、Activity啟動(dòng)過程
最近準(zhǔn)備更新 Android 面試必備基礎(chǔ)知識(shí)系列,有興趣的可以關(guān)注我的微信公眾號(hào) stormjun94,有更新時(shí),第一時(shí)間會(huì)在微信公眾號(hào)上面發(fā)布,同時(shí),也會(huì)同步在 GitHub 上面更新,如果覺得對你有所幫助的話,請幫忙 star。
Android 系統(tǒng)啟動(dòng)過程
從系統(tǒng)層看:
linux 系統(tǒng)層 Android 系統(tǒng)服務(wù)層 Zygote
從開機(jī)啟動(dòng)到 Home Launcher:
啟動(dòng) bootloader (小程序;初始化硬件) 加載系統(tǒng)內(nèi)核 (先進(jìn)入實(shí)模式代碼再進(jìn)入保護(hù)模式代碼) 啟動(dòng) init 進(jìn)程(用戶級(jí)進(jìn)程 ,進(jìn)程號(hào)為1) 啟動(dòng) Zygote 進(jìn)程(初始化Dalvik VM等) 啟動(dòng) Runtime 進(jìn)程 啟動(dòng)本地服務(wù)(system service) 啟動(dòng) HomeLauncher
詳細(xì)解析
Android系統(tǒng)完整的啟動(dòng)過程,從系統(tǒng)層次角度可分為 Linux 系統(tǒng)層、Android 系統(tǒng)服務(wù)層、Zygote進(jìn)程模型三個(gè)階段;從開機(jī)到啟動(dòng) Home Launcher 完成具體的任務(wù)細(xì)節(jié)可分為七個(gè)步驟,下面就從具體的細(xì)節(jié)來解讀 Android 系統(tǒng)完整的初始化過程。
一、啟動(dòng)BootLoader
Android 系統(tǒng)是基于 Linux 操作系統(tǒng)的,所以它最初的啟動(dòng)過程和 Linux 一樣。當(dāng)設(shè)備通電后首先執(zhí)行 BootLoader 引導(dǎo)裝載器,BootLoader 是在操作系統(tǒng)內(nèi)核運(yùn)行之前運(yùn)行的一段小程序。通過這段小程序初始化硬件設(shè)備、建立內(nèi)存空間映射圖,從而將系統(tǒng)的軟硬件環(huán)境引導(dǎo)進(jìn)入合適的狀態(tài),以便為最終調(diào)用操作系統(tǒng)內(nèi)核準(zhǔn)備好正確的運(yùn)行環(huán)境。
而Linux系統(tǒng)啟動(dòng)時(shí):
首先要加載 BIOS 的硬件信息,并獲取第一個(gè)啟動(dòng)設(shè)備的代號(hào)
讀取第一個(gè)啟動(dòng)設(shè)備的MBR的引導(dǎo)加載程序(lilo、grub等)的啟動(dòng)信息。
加載核心操作系統(tǒng)的核心信息,核心開始解壓縮,并且嘗試驅(qū)動(dòng)所有的硬件設(shè)備。
.....
在嵌入式系統(tǒng)中,通常不會(huì)有像 BIOS 那樣的固件程序,因此整個(gè)系統(tǒng)的加載任務(wù)都是通過 BootLoader 完成的。
二、加載系統(tǒng)內(nèi)核
Linux 內(nèi)核映像通常包括兩部分代碼,分別為實(shí)模式代碼和保護(hù)模式代碼。當(dāng) BootLoader 裝載內(nèi)核映像到代碼段內(nèi)存時(shí),分別放置實(shí)模式代碼和保護(hù)模式代碼到不同的位置,然后進(jìn)入實(shí)模式代碼執(zhí)行,實(shí)模式代碼執(zhí)行完成后轉(zhuǎn)入保護(hù)模式代碼。
實(shí)模式和保護(hù)模式的概念再次不做過多解釋,讀者可以自行查閱資料。
三、啟動(dòng)Init進(jìn)程
當(dāng)系統(tǒng)內(nèi)核加載完成之后,會(huì)首先啟動(dòng) Init 守護(hù)進(jìn)程,它是內(nèi)核啟動(dòng)的第一個(gè)用戶級(jí)進(jìn)程,它的進(jìn)程號(hào)總是 1。Init 進(jìn)程啟動(dòng)完成之后,還負(fù)責(zé)啟動(dòng)其他的一些重要守護(hù)進(jìn)程,包括:
Usbd 進(jìn)程(USB Daemon):USB 連接后臺(tái)進(jìn)程,負(fù)責(zé)管理 USB 連接。
adbd 進(jìn)程(Android Debug Bridge Daemon):ADB 連接后臺(tái)進(jìn)程,負(fù)責(zé)管理 ADB 連接。
debuggerd 進(jìn)程(Debugger Daemon) :調(diào)試器后臺(tái)進(jìn)程,負(fù)責(zé)管理調(diào)試請求及調(diào)試過程。
rild 進(jìn)程 (Radio Interface Layer Daemon):無線接口層后臺(tái)進(jìn)程,負(fù)責(zé)管理無線通信服務(wù)。
四、啟動(dòng)Zygote進(jìn)程
Init 進(jìn)程和一些重要的守護(hù)進(jìn)程啟動(dòng)完成之后,系統(tǒng)啟動(dòng) Zygote 進(jìn)程。Zygote 進(jìn)程啟動(dòng)后,首先初始化一個(gè) Dalvik VM實(shí)例,然后為它加載資源與系統(tǒng)共享庫,并開啟 Socket 監(jiān)聽服務(wù),當(dāng)收到創(chuàng)建Dalvik VM 實(shí)例請求時(shí),會(huì)通過COW(copy on write)技術(shù)最大程度地復(fù)用自己,生成一個(gè)新的Dalvik VM 實(shí)例。Dalvik VM 實(shí)例的創(chuàng)建方法基于 linux 系統(tǒng)的 fork 原理。
其實(shí),我個(gè)人理解,Zygote 進(jìn)程就相當(dāng)于Linux系統(tǒng)中的 fork 進(jìn)程。由它可以在系統(tǒng)運(yùn)行期間,接收到創(chuàng)建虛擬機(jī)請求時(shí),孵化 Dalvik VM實(shí)例。Zygote 進(jìn)程孵化 Dalvik VM 實(shí)例流程如下圖所示:

圖1 Zygote進(jìn)程孵化Dalvik VM實(shí)例流程
五 、啟動(dòng)Runtime進(jìn)程
在 Zygote 進(jìn)程啟動(dòng)完成之后,Init 進(jìn)程會(huì)啟動(dòng) Runtime 進(jìn)程。Runtime 進(jìn)程首先初始化服務(wù)管理器(Service Manager),并把它注冊為綁定服務(wù)(Binder services)的默認(rèn)上下文管理器,負(fù)責(zé)綁定服務(wù)的注冊與查找。然后 Runtime 進(jìn)程會(huì)向 Zygote進(jìn)程發(fā)送啟動(dòng)系統(tǒng)服務(wù)(System Service)的請求,Zygote 進(jìn)程收到請求后,會(huì)“孵化”出一個(gè)新的 Dalvik VM 實(shí)例并啟動(dòng)系統(tǒng)服務(wù)進(jìn)程。Runtime 進(jìn)程的啟動(dòng)流程如下圖所示:

圖2 Runtime進(jìn)程啟動(dòng)流程圖
六、啟動(dòng)本地服務(wù)
System Service 會(huì)首先啟動(dòng)兩個(gè)本地服務(wù)(由C或C++編寫的native服務(wù)),Surface Flinger 和Audio Flinger,這兩個(gè)本地系統(tǒng)服務(wù)向服務(wù)管理器注冊成為 IPC 服務(wù)對象,以便在需要它們的時(shí)候很容易查找到。然后 SystemService 會(huì)啟動(dòng)一些 Android 系統(tǒng)管理服務(wù),包括硬件服務(wù)和系統(tǒng)框架核心平臺(tái)服務(wù),并注冊它們成為 IPC 服務(wù)對象。本地服務(wù)進(jìn)程的啟動(dòng)流程如下圖所示:

圖3 SystemService啟動(dòng)本地服務(wù)流程圖
七、啟動(dòng)Home Laucher
當(dāng) SystemService 加載了所有的系統(tǒng)服務(wù)后就意味著系統(tǒng)就準(zhǔn)備好了,它會(huì)向所有服務(wù)發(fā)送一個(gè)系統(tǒng)準(zhǔn)備完畢(systemready) 廣播。SystemService 系統(tǒng)服務(wù)進(jìn)程的啟動(dòng)流程如圖3所示。當(dāng)ActivityManagerService 接收到 systemready 廣播后,會(huì)向Zygoute進(jìn)程發(fā)送創(chuàng)建Dalvik 虛擬機(jī)實(shí)例的請求,Zygoute 進(jìn)程會(huì)負(fù)責(zé)生成一個(gè)新的 Dalvik 虛擬機(jī)實(shí)例,然后 ActivityManagerService 在系統(tǒng)中查找具有<category android:name = "android.intent.category.HOME"/>屬性的Activity,并啟動(dòng)它。ActivityManagerService 同時(shí)也會(huì)使用同樣的方法啟動(dòng) Contact 應(yīng)用程序。

圖4 啟動(dòng)Home Laucher流程圖
APk 安裝過程
Android應(yīng)用安裝有如下四種方式:
1.系統(tǒng)應(yīng)用安裝――開機(jī)時(shí)完成,沒有安裝界面
2.網(wǎng)絡(luò)下載應(yīng)用安裝――通過market應(yīng)用完成,沒有安裝界面
3.ADB 工具安裝――沒有安裝界面。
4.第三方應(yīng)用安裝――通過SD卡里的APK文件安裝,有安裝界面,由 packageinstaller.apk 應(yīng)用處理安裝及卸載過程的界面。
應(yīng)用安裝的流程及路徑
應(yīng)用安裝涉及到如下幾個(gè)目錄:
system/app :系統(tǒng)自帶的應(yīng)用程序,獲得adb root權(quán)限才能刪除
data/app :用戶程序安裝的目錄。安裝時(shí)把 apk文件復(fù)制到此目錄
data/data :存放應(yīng)用程序的數(shù)據(jù)
data/dalvik-cache:將 apk中 的 dex 文件安裝到 dalvik-cache 目錄下(dex 文件是 dalvik 虛擬機(jī)的可執(zhí)行文件,其大小約為原始 apk 文件大小的四分之一)
安裝過程
復(fù)制 APK 安裝包到 data/app 目錄下,解壓并掃描安裝包,把 dex 文件(Dalvik字節(jié)碼)保存到 dalvik-cache 目錄,并在 data/data 目錄下創(chuàng)建對應(yīng)的應(yīng)用數(shù)據(jù)目錄。
App 啟動(dòng)過程
這里以啟動(dòng)微信為例子說明
Launcher 通知 AMS 要啟動(dòng)微信了,并且告訴AMS要啟動(dòng)的是哪個(gè)頁面也就是首頁是哪個(gè)頁面。 AMS 收到消息告訴 Launcher 知道了,并且把要啟動(dòng)的頁面記下來。 Launcher 進(jìn)入Paused狀態(tài),告訴 AMS,你去找微信吧。
上述就是 Launche r和 AMS 的交互過程
AMS 檢查微信是否已經(jīng)啟動(dòng)了也就是是否在后臺(tái)運(yùn)行,如果是在后臺(tái)運(yùn)行就直接啟動(dòng),如果不是,AMS 會(huì)在新的進(jìn)程中創(chuàng)建一個(gè)ActivityThread 對象,并啟動(dòng)其中的 main 函數(shù)。 微信啟動(dòng)后告訴 AMS,啟動(dòng)好了。 AMS 通過之前的記錄找出微信的首頁,告訴微信應(yīng)該啟動(dòng)哪個(gè)頁面。 微信按照AMS通知的頁面去啟動(dòng)就啟動(dòng)成功了。
Activity啟動(dòng)過程
Activity 啟動(dòng)過程是由 ActivityMangerService(AMS) 來啟動(dòng)的,底層 原理是 Binder實(shí)現(xiàn)的 最終交給 ActivityThread 的 performActivity 方法來啟動(dòng)她
ActivityThread 大概可以分為以下五個(gè)步驟
通過 ActivityClientRecoed 對象獲取 Activity 的組件信息 通過 Instrument 的 newActivity 使用類加載器創(chuàng)建 Activity 對象 檢驗(yàn) Application 是否存在,不存在的話,創(chuàng)建一個(gè),保證 只有一個(gè) Application 通過 ContextImpl 和 Activity 的 attach 方法來完成一些初始化操作 調(diào)用 oncreat 方法。
想詳細(xì)了解的可以參考這一篇文章,個(gè)人覺得寫得還不錯(cuò)。
推薦閱讀:
