Android系統(tǒng)的啟動(dòng)

本文用于記錄Android系統(tǒng)相關(guān)知識(shí)點(diǎn)。主要是文字總結(jié)~

一、Android系統(tǒng)架構(gòu)

Android系統(tǒng)架構(gòu)分為五層:
① 應(yīng)用層(APP)
② 應(yīng)用框架層(Framework)
③系統(tǒng)運(yùn)行庫(kù)層(native C/C++,比如OpenGL ES;Android runtime以及Android基礎(chǔ)庫(kù))
④ 硬件抽象層(內(nèi)核與硬件電路之間的接口層)
⑤ Linux內(nèi)核層(內(nèi)存管理,進(jìn)程管理)

二、Android系統(tǒng)啟動(dòng)

① init進(jìn)程

init進(jìn)程是Android系統(tǒng)中用戶空間的第一個(gè)進(jìn)程,被賦予了很多重要的職責(zé),比如創(chuàng)建Zygote和屬性服務(wù)等。

介紹init之前,先了解系統(tǒng)的啟動(dòng):

  • 當(dāng)電源按下時(shí)引導(dǎo)芯片代碼從預(yù)定的地方(固化在ROM)開(kāi)始執(zhí)行。加載引導(dǎo)程序BootLoader到RAM中,然后執(zhí)行。BootLoader是Android系統(tǒng)運(yùn)行前的一個(gè)小程序,負(fù)責(zé)把系統(tǒng)OS拉起來(lái)并運(yùn)行。
  • 當(dāng)內(nèi)核啟動(dòng)時(shí),設(shè)置緩存,被保護(hù)存儲(chǔ)器,計(jì)劃列表,加載驅(qū)動(dòng)。在內(nèi)核完成系統(tǒng)設(shè)置后,會(huì)在系統(tǒng)文件中尋找init.rc文件,并啟動(dòng)init進(jìn)程。
  • init進(jìn)程用來(lái)初始化和啟動(dòng)屬性服務(wù),也用來(lái)啟動(dòng)Zygote進(jìn)程。

簡(jiǎn)單說(shuō)就是,順序就是:

引導(dǎo)程序 ??????  Linux內(nèi)核  ??????  init進(jìn)程

從init進(jìn)程的main函數(shù)可以看出,它主要是做了以下三件事:

  • 創(chuàng)建和掛在啟動(dòng)所需的文件目錄
  • 初始化和啟動(dòng)屬性服務(wù)。(屬性服務(wù)類(lèi)似注冊(cè)表管理器,用鍵值對(duì)記錄用戶和軟件的一些使用信息,在系統(tǒng)或軟件重啟時(shí),能根據(jù)這些記錄,進(jìn)行相應(yīng)的初始化)
  • 解析init.rc 配置文件并啟動(dòng)Zygote進(jìn)程。

② Zygote進(jìn)程

Zygote之所以叫孵化器,是因?yàn)镈VM和ART,應(yīng)用程序進(jìn)程以及運(yùn)行系統(tǒng)的關(guān)鍵服務(wù)的SystemServer進(jìn)程都是由Zygote進(jìn)程所創(chuàng)建的。
Zygote進(jìn)程在啟動(dòng)時(shí)會(huì)創(chuàng)建DVM或者ART,通過(guò)fork而創(chuàng)建的APP進(jìn)程以及SystemServer進(jìn)程可以在內(nèi)部獲取一個(gè)DVM或者ART的實(shí)例副本。

在init.rc(使用的是Android Init Language)中決定要啟動(dòng)哪一個(gè)Zygote腳本(使用的是Android Init Language)。

init啟動(dòng)Zygote,會(huì)找到要啟動(dòng)的Zygote腳本,判斷進(jìn)程是否啟動(dòng),如果沒(méi)有就fork函數(shù)創(chuàng)建子進(jìn)程,并返回pid值。如果進(jìn)程被啟動(dòng),就會(huì)進(jìn)入Zygote的main函數(shù),也就是app_main.cpp的main函數(shù)中,并調(diào)用runtime的start函數(shù)啟動(dòng)ZygoteInit。

Zygote進(jìn)程都是通過(guò)fork創(chuàng)建子進(jìn)程,所以它們都可以進(jìn)入app_main.cpp的main函數(shù)。main函數(shù)的參數(shù)可以判斷該進(jìn)程是什么進(jìn)程(是Zygote還是SystemServer還是其他)。
如果是Zygote進(jìn)程,會(huì)調(diào)用AppRuntime的start函數(shù)。該函數(shù)會(huì)先創(chuàng)建java虛擬機(jī),為虛擬機(jī)注冊(cè)JNI方法。通過(guò)參數(shù)(ZygoteInit的名字)找到ZygoteInit的main方法,并通過(guò)JNI調(diào)用該main的方法。也就是這里從Native層進(jìn)入Java框架層。

ZygoteInit的main函數(shù)主要做了四件事:

  • ZygoteServer創(chuàng)建一個(gè)Server端的Scoket(ScoketName為zygote,用來(lái)等待AMS請(qǐng)求Zygote進(jìn)程賚 創(chuàng)建新的應(yīng)用程序進(jìn)程)
  • 預(yù)加載類(lèi)和資源
  • 啟動(dòng)SystemServer進(jìn)程(Zygote通過(guò)fork,進(jìn)程名為system_server)
  • 等待AMS請(qǐng)求創(chuàng)建新的應(yīng)用程序進(jìn)程(ZygoteServer的runSelectLoop,無(wú)限循環(huán)等待AMS的請(qǐng)求)

所以從上面來(lái)看,程序運(yùn)行的順序如下:

app_main  ??????  AndroidRuntime ?????? ZygoteInit ?????? ZygoteServer

Zygote進(jìn)程啟動(dòng)總結(jié):

  • 創(chuàng)建AppRuntime并調(diào)用其start方法,啟動(dòng)Zygote進(jìn)程。
  • 創(chuàng)建java虛擬機(jī)并為java虛擬機(jī)注冊(cè)JNI方法。
  • 通過(guò)JINI調(diào)用ZygoteInit的main函數(shù)進(jìn)入Zygote的java框架層。
  • 通過(guò)registerZygoteSocket方法創(chuàng)建服務(wù)器端Scoket,并通過(guò)runSelectLoop方法等待AMS的請(qǐng)求來(lái)創(chuàng)建新的應(yīng)用程序。
  • 啟動(dòng)SystemServer進(jìn)程。

③ SystemServer進(jìn)程

SystemServer進(jìn)程用于創(chuàng)建系統(tǒng)服務(wù)(AMS,WMS和PMS等)。
SystemServer是在ZygoteInit的startSystemServer方法中啟動(dòng)的,SystemServer進(jìn)程是Zygote的fork,需要關(guān)閉對(duì)其進(jìn)程沒(méi)用的Socket。
除了startSystemServer還要執(zhí)行handleSystemServerProcess,即處理SystemServer進(jìn)程,主要的處理呢有啟動(dòng)Binder線程池(nativeZygoteInit)和進(jìn)入SystemServer的main方法。

ZygoteInit  ??????  SystemServer

nativeZygoteInit是一個(gè)JNI方法,底層是AppRuntime的onZygoteInitonZygoteInit主要是啟動(dòng)線程池。

進(jìn)入SystemServer是通過(guò)RuntimeInit的applicationInit,接著調(diào)用invokeStaticMain,通過(guò)反射得到SystemServer類(lèi),找到SystemServer類(lèi)的main方法,通過(guò)Zygote中的靜態(tài)類(lèi)MethodAndArgsCaller動(dòng)態(tài)調(diào)用(這個(gè)有點(diǎn)不理解?)。

接下來(lái)就直行道SystemServer的main函數(shù),main函數(shù)主要有以下作用:

  • 創(chuàng)建消息Looper
  • 加載動(dòng)態(tài)庫(kù)
  • 創(chuàng)建SystemServiceManager(會(huì)對(duì)系統(tǒng)服務(wù)進(jìn)行創(chuàng)建、啟動(dòng)和生命周期管理)
  • 啟動(dòng)服務(wù)(引導(dǎo)服務(wù)、核心服務(wù)、其他服務(wù)),啟動(dòng)比較簡(jiǎn)單,直接通過(guò)startServer,并添加在mServices中。

所以,SystemServer的啟動(dòng)流程主要經(jīng)過(guò)了以下的過(guò)程:

Zygote ?????? AndroidRuntime ??????  RuntimeInit ?????? MethodAndArgsCaller ?????? systemServer

SystemServer的主要工作:

  • 啟動(dòng)Binder線程池,這樣就可以與其他進(jìn)程進(jìn)行通信。
  • 創(chuàng)建SystemServiceManager,用于對(duì)系統(tǒng)服務(wù)的創(chuàng)建、啟動(dòng)和生命周期管理
  • 啟動(dòng)各種系統(tǒng)服務(wù)

④ Launcher進(jìn)程

Launcher是Android系統(tǒng)的桌面,也是一個(gè)應(yīng)用程序,用來(lái)啟動(dòng)應(yīng)用程序和管理應(yīng)用程序的圖標(biāo)。Launcher在啟動(dòng)過(guò)程中會(huì)請(qǐng)求PMS返回安裝的應(yīng)用程序的信息,從而才能展示。
SystemService進(jìn)程啟動(dòng)過(guò)程中會(huì)啟動(dòng)PMS,PMS啟動(dòng)后會(huì)將系統(tǒng)中的應(yīng)用程序安裝完成。然后已經(jīng)啟動(dòng)的AMS會(huì)把Launcher啟動(dòng)起來(lái)。

在SystemServer的startOtherServices中,AMS會(huì)調(diào)用systemReady。systemReady里面
ActivityStackSupervisor(監(jiān)督者)去resumeXXX,底層是讓ActivityStack去resumeXXX,饒了一圈,最終會(huì)調(diào)用AMS的startHomeActivityLocked。
其中的調(diào)用流程如下圖:

SystemServer ?????? AMS ?????? ActivityStackSupervisor ?????? ActivityStack 
?????? ActivityStackSupervisor ??????  AMS

AMS的startHomeActivityLocked是最終啟動(dòng)的關(guān)鍵,創(chuàng)建了Launcher啟動(dòng)所需的Intent,Launcher是一個(gè)程序,所以有對(duì)應(yīng)的AndroidManifest.xml,通過(guò)AndroidManifest.xml的action和category可以有符合的應(yīng)用程序已經(jīng)啟動(dòng),沒(méi)有的話調(diào)用ActivityStarterde startHomeActivityLocked來(lái)啟動(dòng)Launcher。在 startHomeActivityLocked``中,會(huì)啟動(dòng)Launcher,并進(jìn)入Launcher的onCreate```。

Launcher啟動(dòng)后還會(huì)做很多工作,比如顯示應(yīng)用程序圖標(biāo)。這些都是在onCreate中完成。

那應(yīng)用程序圖標(biāo)是怎么顯示的呢?

onCreate中,主要涉及到以下這些類(lèi):

Launcher ?????? LauncherAppState  ??????  LauncherModel

最終會(huì)在LauncherModel的startLoader里面創(chuàng)建具有消息循環(huán)的線程HandlerThread對(duì)象,創(chuàng)建Handler,傳入HandlerThread的Looper。也就需要子線程來(lái)處理某個(gè)任務(wù),這個(gè)任務(wù)就是LauncherModel的內(nèi)部類(lèi)LoaderTask,LoaderTask主要用來(lái)加載工作區(qū)信息和綁定工作區(qū)信息(Launcher是用工作區(qū)的形式來(lái)顯示系統(tǒng)安裝的應(yīng)用程序的圖標(biāo)的),以及加載系統(tǒng)已經(jīng)安裝的應(yīng)用程序信息loadAllApps,但是loadAllApps是用了mHandler的post方法,所以加載app信息這塊實(shí)際上跳到主線程去執(zhí)行,loadAllApps實(shí)際上又調(diào)用了Launcher的bindAllApplications,而bindAllApplications其實(shí)就是設(shè)置UI(mAppView)。mAppView是一個(gè)AllAppsContainerView,將app信息數(shù)組傳遞給mAppView的setApps方法,mAppView在其onFinishInflate利用recycleView實(shí)現(xiàn)app信息的展示。

這樣圖標(biāo)的顯示流程就結(jié)束了。

⑤ APP進(jìn)程

要啟動(dòng)APP,AMS要先檢查APP所需的APP進(jìn)程是否存在,不存在就會(huì)請(qǐng)求Zygote進(jìn)程啟動(dòng)需要的APP進(jìn)程。Zygote創(chuàng)建的Scoket就是用來(lái)等待AMS請(qǐng)求Zygote來(lái)創(chuàng)建新的APP進(jìn)程。Zygote進(jìn)程通過(guò)Fork自身創(chuàng)建APP進(jìn)程,APP進(jìn)程就會(huì)獲得Zygote在啟動(dòng)時(shí)創(chuàng)建的虛擬機(jī)實(shí)例,也創(chuàng)建了Binder線程池和消息循環(huán)。

所以,APP進(jìn)程的啟動(dòng)通過(guò)分割可以分為兩個(gè)步驟:

  • AMS發(fā)送啟動(dòng)APP進(jìn)程請(qǐng)求
  • Zygote接受請(qǐng)求并創(chuàng)建APP進(jìn)程
AMS發(fā)送啟動(dòng)APP進(jìn)程請(qǐng)求

AMS通過(guò)調(diào)用startProcessLocked方法向Zygote進(jìn)程發(fā)送請(qǐng)求。在startProcessLocked主要處理數(shù)據(jù)(用戶ID,線程名等),然后調(diào)用Process(線程類(lèi))的start,又跳轉(zhuǎn)到ZygoteProcess的startstartViaZygote,在startViaZygote中,會(huì)講應(yīng)用進(jìn)程的啟動(dòng)參數(shù)保存在argsForZygote中,方法的最后會(huì)調(diào)用zygoteSendArgsAndGetResult。zygoteSendArgsAndGetResult需要兩個(gè)參數(shù)ZygoteState和argsForZygote,ZygoteState是ZygoteProcessopenZygoteSocketIfNeeded返回的,在openZygoteSocketIfNeeded中,與Zygote進(jìn)程建立Scoket連接,并返回ZygoteState。這邊有點(diǎn)繞,ZygoteProcess不是Zygote進(jìn)程的角色,是用來(lái)保持與Zygote進(jìn)程的通信狀態(tài),ZygoteState是ZygoteProcess的靜態(tài)內(nèi)部類(lèi),用來(lái)表示與Zygote進(jìn)程通信的狀態(tài)。

走到這步,ZygoteProcess與Zygote進(jìn)程算是連接成功了,zygoteSendArgsAndGetResult會(huì)將argsForZygote寫(xiě)入到ZygoteState,Zygote進(jìn)程會(huì)通過(guò)ZygoteState收到一個(gè)創(chuàng)建新的APP進(jìn)程的請(qǐng)求。

所以,大概的流程如下:

AMS  ??????  Process  ??????   ZygoteProcess  ??????  ZygoteState

ZygoteState是一個(gè)最終的橋梁。

Zygote接受請(qǐng)求并創(chuàng)建APP進(jìn)程

在之前講到的中,ZygoteInit的main中,zygoteServer會(huì)創(chuàng)建Scoket,runSelectLoop來(lái)等待AMS請(qǐng)求。那runSelectLoop又做了哪些事?runSelectLoop開(kāi)啟了一個(gè)死循環(huán),用來(lái)等待ZygoteConnection的runOnce執(zhí)行,```runOnce``做了以下的事情

  • 獲取應(yīng)用程序進(jìn)程的啟動(dòng)參數(shù)
  • 封裝成新的參數(shù)
  • 創(chuàng)建應(yīng)用程序進(jìn)程
  • 關(guān)閉Socket(不需要Socket)
  • 處理應(yīng)用程序進(jìn)程(ZygoteInit的zygoteInit

其他幾條好理解,處理應(yīng)用程序進(jìn)程是執(zhí)行ZygoteInit的zygoteInit,又讓RuntimeInit和ZygoteInit做了一些事,概括起來(lái)就是創(chuàng)建Binder線程池,通過(guò)反射獲取到ActivityThread類(lèi)和main方法,最終執(zhí)行其main方法,至此就是完成APP進(jìn)程的創(chuàng)建并運(yùn)行了主線程的管理類(lèi)ActivityThread。

大概的流程如下:

Zygote  ??????  ZygoteServer  ??????   ZygoteConnection  ??????  RuntimeInit   ??????  ActivityThread

還有一個(gè)需要補(bǔ)充的點(diǎn), Binder線程池的啟動(dòng)過(guò)程

Binder線程池的啟動(dòng)在ZygoteInit的zygoteInit方法中,是調(diào)用ZygoteInit的nativeZygoteInit,這是一個(gè)JNI方法,對(duì)應(yīng)的CPP實(shí)現(xiàn)是AndroidRuntime的方法,AppRuntime繼承自AndroidRuntime,最終又是調(diào)用AppRuntime的onZygoteInit(實(shí)現(xiàn)在app_main.cpp),通過(guò)ProcessState的startThreadPool來(lái)啟動(dòng)Binder線程池。
支持Binder通信的進(jìn)程中都有一個(gè)ProcessState類(lèi),其中有個(gè)mThreadPoolStarted屬性來(lái)保證被啟動(dòng)一次。沒(méi)有啟動(dòng)的情況會(huì)調(diào)用spawnPooledThread來(lái)創(chuàng)建線程池的第一個(gè)線程,也就是線程池的主線程。
Binder線程是PoolThread類(lèi)型(繼承Thread),在創(chuàng)建的時(shí)候會(huì)將當(dāng)前線程注冊(cè)到Binder驅(qū)動(dòng)程序中,這樣該線程也加入了Binder線程池中,新創(chuàng)建的APP進(jìn)程也就支持Binder進(jìn)程間通信了。
我們只需創(chuàng)建當(dāng)前進(jìn)程的Binder對(duì)象,并將它注冊(cè)到ServiceManager中就可以實(shí)現(xiàn)Binder進(jìn)程間通信,而不必關(guān)心進(jìn)程間是如何通過(guò)Binder進(jìn)行通信的。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容