Android 系統(tǒng)的啟動流程
Android 系統(tǒng)的啟動流程可以分為以下幾個主要步驟:
-
引導(dǎo)加載器(Bootloader)啟動:當(dāng)你打開一個 Android 設(shè)備時,首先啟動的是引導(dǎo)加載器。引導(dǎo)加載器負(fù)責(zé)啟動 Android 的核心操作系統(tǒng)。
-
Linux 內(nèi)核啟動:引導(dǎo)加載器加載并啟動 Linux 內(nèi)核。Linux 內(nèi)核負(fù)責(zé)啟動系統(tǒng)的底層硬件,并啟動 init 進(jìn)程。
-
Init 進(jìn)程啟動:init 進(jìn)程是 Linux 系統(tǒng)中的第一個進(jìn)程(PID = 1)。在 Android 系統(tǒng)中,init 進(jìn)程負(fù)責(zé)啟動一些重要的守護(hù)進(jìn)程和服務(wù),例如 Zygote 進(jìn)程。
-
Zygote 進(jìn)程啟動:Zygote 是 Android 中的一個特殊進(jìn)程,負(fù)責(zé)孵化(Fork)出所有其他的應(yīng)用進(jìn)程。Zygote 進(jìn)程在啟動時會預(yù)加載大量的系統(tǒng)類和資源,以此來提高應(yīng)用啟動的速度。
-
SystemServer 進(jìn)程啟動:Zygote 進(jìn)程會 fork 出一個新的進(jìn)程來啟動 SystemServer。SystemServer 是 Android 系統(tǒng)中的核心服務(wù),它管理并提供了許多系統(tǒng)級別的服務(wù),例如窗口管理服務(wù)、活動管理服務(wù)等。
-
系統(tǒng)服務(wù)啟動:在 SystemServer 進(jìn)程中,會啟動各種系統(tǒng)服務(wù)。這些服務(wù)在系統(tǒng)啟動完成后,將一直運行,為應(yīng)用程序提供各種服務(wù)。
-
啟動 Launcher 應(yīng)用:系統(tǒng)服務(wù)啟動完畢后,Activity Manager Service 會啟動設(shè)備的 Launcher 應(yīng)用,此時,用戶可以開始與設(shè)備進(jìn)行交互。
這就是 Android 系統(tǒng)啟動的整個過程。請注意,這個過程可能會因設(shè)備制造商的定制和 Android 版本的不同而有所不同,但大體流程是相同的。
Launcher的啟動流程
Launcher 的啟動過程更具體的說明如下:
-
當(dāng) Android 系統(tǒng)啟動完成,并且所有的系統(tǒng)服務(wù)都已經(jīng)啟動后,ActivityManagerService (AMS)會開始處理用戶的交互。AMS 是 Android 中負(fù)責(zé)管理所有活動的系統(tǒng)服務(wù)。
-
AMS 會發(fā)送一個包含 ACTION_MAIN 和 CATEGORY_HOME 的 Intent。這個 Intent 的目的是尋找并啟動設(shè)備上配置為主屏幕(HOME)的應(yīng)用,通常這就是 Launcher 應(yīng)用。
-
這個 Intent 會通過 Android 的 Intent 解析系統(tǒng),尋找所有能夠響應(yīng)這個 Intent 的應(yīng)用。由于 Launcher 在其清單文件(AndroidManifest.xml)中聲明了相應(yīng)的 ,因此它會被選中來響應(yīng)這個 Intent。
-
一旦 Launcher 被選中,AMS 就會請求 Launcher 啟動。如果這是設(shè)備第一次啟動,或者 Launcher 進(jìn)程尚未啟動,那么 AMS 會請求 Zygote 啟動一個新的進(jìn)程來托管 Launcher。如果 Launcher 進(jìn)程已經(jīng)存在,AMS 就會在該進(jìn)程中啟動新的 Launcher 活動實例。
-
當(dāng) Launcher 啟動后,它會創(chuàng)建并顯示用戶的主屏幕。這個屏幕上會顯示應(yīng)用的圖標(biāo)、小部件等,用戶可以通過這個界面啟動和切換應(yīng)用。
startActivity 詳細(xì)說明
-
發(fā)送 Intent:源應(yīng)用程序(App1)調(diào)用 startActivity 方法,傳遞一個 Intent。該 Intent 包含要啟動的目標(biāo)應(yīng)用程序(App2)的 Activity 的信息。
-
驗證權(quán)限和 Intent:在 ActivityManagerService (AMS) 中,startActivity 方法會對 Intent 進(jìn)行檢查和驗證。這包括驗證調(diào)用者的權(quán)限,查找 Intent 對應(yīng)的 Activity,處理各種啟動模式等。
-
判斷目標(biāo)應(yīng)用程序進(jìn)程狀態(tài):接著,AMS 會判斷目標(biāo)應(yīng)用程序 App2 的進(jìn)程是否已經(jīng)存在。如果已經(jīng)存在,AMS 會使用已經(jīng)存在的進(jìn)程;如果不存在,AMS 會向 Zygote 發(fā)送請求,要求它創(chuàng)建一個新的進(jìn)程。
-
創(chuàng)建新的應(yīng)用程序進(jìn)程:Zygote 在收到 AMS 的請求后,會創(chuàng)建一個新的應(yīng)用程序進(jìn)程,然后在這個進(jìn)程中創(chuàng)建一個 Application 對象,并執(zhí)行其 onCreate 方法。
-
創(chuàng)建 ActivityRecord:與此同時,AMS 會創(chuàng)建一個新的 ActivityRecord 對象,來代表要啟動的 Activity。
-
調(diào)度啟動 Activity:然后,AMS 會通過 Binder IPC 向新的應(yīng)用程序進(jìn)程發(fā)送一個 LAUNCH_ACTIVITY 消息。
-
接收 LAUNCH_ACTIVITY 消息:新的應(yīng)用程序進(jìn)程在接收到 LAUNCH_ACTIVITY 消息后,會創(chuàng)建目標(biāo) Activity 的實例,然后調(diào)用其 onCreate、onStart 和 onResume 方法。
ActivityManagerService 啟動
**ActivityManagerService (AMS) **是 Android 中最為關(guān)鍵的系統(tǒng)服務(wù)之一,它負(fù)責(zé)管理系統(tǒng)中的進(jìn)程,以及四大組件(Activity、Service、BroadcastReceiver 和 ContentProvider)的生命周期。這里將詳細(xì)解釋 AMS 的內(nèi)部啟動流程和工作流程:
AMS的啟動流程:
實例化:AMS 是在 SystemServer 中被實例化的。SystemServer 會首先創(chuàng)建一個 ContextImpl 對象,然后利用這個 ContextImpl 創(chuàng)建 AMS。
服務(wù)初始化:接下來,調(diào)用 AMS 的 init 方法進(jìn)行初始化,這個方法會創(chuàng)建和初始化一些需要的數(shù)據(jù)結(jié)構(gòu)和服務(wù),比如 BroadcastQueue、IntentFirewall 和 ActivityStackSupervisor 等。
準(zhǔn)備完成:完成初始化后,調(diào)用 systemReady 方法來通知 AMS 系統(tǒng)準(zhǔn)備就緒。在這個方法中,AMS 會完成一些后期初始化的工作,例如啟動系統(tǒng)的 Home Activity。
AMS的工作流程:
AMS 主要的工作就是管理系統(tǒng)中的四大組件和進(jìn)程。以下是它們分別的工作流程:
Activity的管理:AMS 使用 ActivityStackSupervisor 來管理系統(tǒng)中所有的 Activity。當(dāng)應(yīng)用程序調(diào)用 startActivity 方法時,會通過 Binder IPC 機制調(diào)用 AMS 中的 startActivity 方法。AMS 會根據(jù) Intent 解析出需要啟動的 Activity,創(chuàng)建一個 ActivityRecord 對象并添加到 ActivityStack 中。然后,AMS 會向應(yīng)用程序發(fā)送 LAUNCH_ACTIVITY 消息,告訴應(yīng)用程序啟動新的 Activity。
Service的管理:當(dāng)應(yīng)用程序調(diào)用 startService 或 bindService 方法時,AMS 會創(chuàng)建一個 ServiceRecord 對象來保存 Service 的狀態(tài)。然后,AMS 會向應(yīng)用程序發(fā)送 CREATE_SERVICE 或 BIND_SERVICE 消息,告訴應(yīng)用程序創(chuàng)建或綁定 Service。
BroadcastReceiver的管理:當(dāng)應(yīng)用程序調(diào)用 sendBroadcast 方法時,AMS 會創(chuàng)建一個 BroadcastRecord 對象,保存廣播的信息。然后,AMS 會將 BroadcastRecord 添加到 BroadcastQueue 中,等待處理。
ContentProvider的管理:當(dāng)應(yīng)用程序調(diào)用 getContentResolver().query() 或其他方法時,AMS 會查找對應(yīng)的 ContentProviderRecord,然后通過 Binder IPC 機制向目標(biāo) ContentProvider 發(fā)送請求。
進(jìn)程的管理:AMS 使用 ProcessList 和 ProcessRecord 來管理系統(tǒng)中的進(jìn)程。當(dāng)需要創(chuàng)建新的進(jìn)程時,AMS 會向 Zygote 發(fā)送請求,然后由 Zygote 創(chuàng)建新的進(jìn)程。同時,AMS 也負(fù)責(zé)進(jìn)程的調(diào)度和回收。
主要信息
startProcessLocked
在 Android 中,startProcessLocked() 方法主要是在 ActivityManagerService 中,用于啟動新的應(yīng)用進(jìn)程。這個方法會被系統(tǒng)在需要啟動新的應(yīng)用進(jìn)程時調(diào)用,例如,當(dāng)用戶啟動一個新的應(yīng)用或者服務(wù)需要在新的進(jìn)程中運行時。以下是一些主要的步驟和操作:
檢查是否已經(jīng)存在相同的進(jìn)程:首先,系統(tǒng)會檢查是否已經(jīng)存在一個相同名字的進(jìn)程。如果已經(jīng)存在,則不會再創(chuàng)建新的進(jìn)程。
檢查系統(tǒng)資源限制:系統(tǒng)會檢查當(dāng)前的系統(tǒng)資源,如內(nèi)存使用情況等,來決定是否有足夠的資源啟動新的進(jìn)程。
創(chuàng)建進(jìn)程記錄:如果可以啟動新的進(jìn)程,系統(tǒng)會創(chuàng)建一個新的 ProcessRecord 對象來保存新進(jìn)程的信息。
啟動新進(jìn)程:使用 Zygote 啟動新進(jìn)程。Zygote 是 Android 中的一個特殊進(jìn)程,它預(yù)加載了大量的系統(tǒng)資源和常用庫,新的應(yīng)用進(jìn)程會通過 fork Zygote 進(jìn)程的方式啟動,這樣可以提高進(jìn)程啟動的速度。
設(shè)置進(jìn)程的參數(shù):系統(tǒng)會設(shè)置新進(jìn)程的各種參數(shù),例如進(jìn)程的優(yōu)先級、所屬用戶等。
更新系統(tǒng)狀態(tài):系統(tǒng)會更新當(dāng)前的系統(tǒng)狀態(tài),例如更新當(dāng)前運行的進(jìn)程列表等。
runOnce
**runOnce()**方法在Android的Zygote進(jìn)程中非常關(guān)鍵,它是處理進(jìn)程啟動請求的主要邏輯。
在Android系統(tǒng)中,新的應(yīng)用進(jìn)程是通過fork Zygote進(jìn)程來創(chuàng)建的。具體來說,當(dāng)需要啟動新的應(yīng)用進(jìn)程時,系統(tǒng)會通過一個特殊的socket與Zygote進(jìn)程進(jìn)行通信,向Zygote進(jìn)程發(fā)送一個包含新進(jìn)程需要的信息的請求,Zygote進(jìn)程在接收到請求后,會執(zhí)行**runOnce()**方法來處理這個請求。
以下是runOnce()方法的主要步驟:
讀取請求參數(shù):runOnce()方法首先會從Zygote socket中讀取請求參數(shù),這些參數(shù)包括新進(jìn)程的一些信息,例如應(yīng)用的包名、啟動類名等。
fork新進(jìn)程:讀取完請求參數(shù)后,runOnce()方法會調(diào)用forkAndSpecialize()或forkSystemServer()方法來fork一個新的進(jìn)程。這兩個方法的主要區(qū)別在于,forkAndSpecialize()方法是用于創(chuàng)建普通的應(yīng)用進(jìn)程,而forkSystemServer()方法是用于創(chuàng)建System Server進(jìn)程。
初始化新進(jìn)程:fork新進(jìn)程后,**runOnce()**方法會對新進(jìn)程進(jìn)行一些初始化操作,例如設(shè)置新進(jìn)程的環(huán)境變量、加載應(yīng)用的dex文件等。
啟動新進(jìn)程的主類:初始化完成后,runOnce()方法會調(diào)用RuntimeInit.zygoteInit()方法來啟動新進(jìn)程的主類。對于普通的應(yīng)用進(jìn)程,主類通常是應(yīng)用的Application類;對于System Server進(jìn)程,主類是com.android.server.SystemServer類。
返回新進(jìn)程的PID:最后,**runOnce()**方法會將新進(jìn)程的PID返回給系統(tǒng)。這個PID是新進(jìn)程的唯一標(biāo)識,系統(tǒng)可以使用這個PID來管理新進(jìn)程。
ActivityThread的main函數(shù)
ActivityThread 是 Android 中的一個非常重要的類,它是每個 Android 應(yīng)用程序主線程的入口點,也就是應(yīng)用程序的主線程(“main” thread)。在 ActivityThread 的 main 方法中,執(zhí)行了一系列的初始化操作來啟動和設(shè)置應(yīng)用程序。
以下是 ActivityThread 的 main 方法主要做了哪些事情:
設(shè)置 Thread 屬性:主線程的名稱會被設(shè)置為** “main”**。
創(chuàng)建 Looper:在 Android 中,主線程需要一個 Looper 對象來處理消息隊列。Looper.prepareMainLooper() 方法會創(chuàng)建一個綁定到主線程的 Looper 對象。
創(chuàng)建 ActivityThread 對象:創(chuàng)建 ActivityThread 實例并調(diào)用其 attach 方法,這個方法會完成一些重要的初始化工作,包括設(shè)置應(yīng)用的上下文,創(chuàng)建應(yīng)用的 Instrumentation 對象等。
設(shè)置 Android 默認(rèn)的異常處理器:如果應(yīng)用拋出未捕獲的異常,這個處理器將會被調(diào)用。
開始循環(huán):通過調(diào)用 Looper.loop() 來開始主線程的消息循環(huán)。
在應(yīng)用進(jìn)程啟動后,需要向 ActivityManagerService (AMS) 報告是因為 AMS 是 Android 系統(tǒng)中管理所有應(yīng)用程序生命周期的關(guān)鍵組件。當(dāng)一個新的應(yīng)用程序進(jìn)程被創(chuàng)建時,它需要告訴 AMS 它已經(jīng)啟動并且準(zhǔn)備好接收指令。此外,這也是一個錯誤檢查機制:如果 AMS 啟動了一個進(jìn)程,但是這個進(jìn)程在一段時間內(nèi)沒有報告回來,那么 AMS 會認(rèn)為這個進(jìn)程啟動失敗,會采取相應(yīng)的操作,如重新啟動這個進(jìn)程或者報告一個錯誤。
啟動binder機制
Binder 機制主要在應(yīng)用程序啟動時進(jìn)行初始化,并在其進(jìn)程生命周期內(nèi)保持活動狀態(tài),用于處理進(jìn)程間通信(IPC)的請求。關(guān)于 Binder 機制的啟動,這主要發(fā)生在應(yīng)用程序的主線程(ActivityThread)初始化過程中。
以下是 Binder 機制的啟動過程:
創(chuàng)建應(yīng)用的主線程:每個** Android** 應(yīng)用都有一個主線程,它是應(yīng)用程序的入口點。當(dāng)新的應(yīng)用程序進(jìn)程創(chuàng)建時,Zygote會復(fù)制其內(nèi)存空間,并在新的進(jìn)程空間中啟動應(yīng)用的主線程。主線程的入口函數(shù)是 ActivityThread.main()。
初始化 Looper:在 ActivityThread.main() 函數(shù)中,會調(diào)用 Looper.prepareMainLooper() 來為主線程創(chuàng)建一個 Looper。Looper 是一個用于處理消息隊列的工具,是實現(xiàn)事件驅(qū)動編程的關(guān)鍵組件。
創(chuàng)建 ActivityThread 對象:接下來,會創(chuàng)建一個 ActivityThread 對象,并調(diào)用其 attach() 方法來進(jìn)行一些必要的初始化工作。在這個過程中,會創(chuàng)建應(yīng)用的 Context,Instrumentation 對象等。
創(chuàng)建 Binder 線程池:在 ActivityThread 的 attach() 方法中,會調(diào)用 BinderInternal.addGcWatcher() 和 BinderInternal.createBinderThreadPool() 來為當(dāng)前進(jìn)程創(chuàng)建 Binder 線程池。
addGcWatcher() 方法會添加一個 GC(垃圾回收)監(jiān)聽器,該監(jiān)聽器會在每次完成 Binder 事務(wù)后執(zhí)行一次 GC,以防止 Binder 事務(wù)造成的內(nèi)存泄漏。
createBinderThreadPool() 方法會創(chuàng)建一個 Binder 線程池。這個線程池會在后臺運行,用于處理來自其他進(jìn)程的 Binder 請求。
啟動消息循環(huán):最后,主線程的 Looper 對象會調(diào)用其 loop() 方法來啟動消息循環(huán)。在這個消息循環(huán)中,主線程會不斷地從消息隊列中取出消息并處理,包括處理來自 Binder 線程池的消息。
Binder Native 層
打開 Binder 驅(qū)動:在 Android 系統(tǒng)啟動的過程中,會加載 Binder 驅(qū)動。在每個進(jìn)程創(chuàng)建的過程中,會打開 /dev/binder 設(shè)備,這樣,該進(jìn)程就可以使用 Binder 驅(qū)動進(jìn)行 IPC 通信了。
映射內(nèi)存:當(dāng)進(jìn)程打開 /dev/binder 設(shè)備后,會通過 mmap 系統(tǒng)調(diào)用映射一塊內(nèi)存空間作為進(jìn)程和 Binder 驅(qū)動之間的通信區(qū)域。這樣,進(jìn)程和 Binder 驅(qū)動就可以通過這塊共享內(nèi)存進(jìn)行數(shù)據(jù)交換,提高了通信效率。
創(chuàng)建 Binder 線程池:每個進(jìn)程都需要創(chuàng)建一個 Binder 線程池來處理來自其他進(jìn)程的 Binder 請求。Binder 線程池是一個由多個線程組成的線程池,每個線程都會使用 ioctl 系統(tǒng)調(diào)用進(jìn)入到 Binder 驅(qū)動的等待隊列,等待來自其他進(jìn)程的 Binder 請求。文章來源:http://www.zghlxwxcb.cn/news/detail-622160.html
當(dāng)一個進(jìn)程通過 Binder 機制向另一個進(jìn)程發(fā)送請求時,Binder 驅(qū)動會喚醒等待隊列中的一個線程來處理這個請求。這個線程會讀取共享內(nèi)存中的數(shù)據(jù),處理請求,并將結(jié)果寫回到共享內(nèi)存中。然后,這個線程會再次進(jìn)入到 Binder 驅(qū)動的等待隊列,等待下一次的請求。文章來源地址http://www.zghlxwxcb.cn/news/detail-622160.html
冷啟動 App 全流程
- 點擊桌面圖標(biāo)后,Launcher 應(yīng)用會構(gòu)建一個 intent 并發(fā)送給 AMS,通知 AMS 啟動 App;
- AMS 收到 intent 消息后,首先做一些校驗,然后判斷 App 對應(yīng)的進(jìn)程是否啟動,如果沒有啟動,則通知 Zygote 進(jìn)程啟動 App;
- AMS 通過 socket 與 Zygote 進(jìn)程通信,將必要的啟動參數(shù)傳遞過去,Zygote 進(jìn)程收到后,通過 fork 調(diào)用創(chuàng)建新的進(jìn)程,并且在主進(jìn)程中將子進(jìn)程的 pid 返回給 AMS 所在的進(jìn)程;
- fork 出來的進(jìn)程也就是 App 進(jìn)程,進(jìn)程啟動后首先會初始化 Binder 機制,具體為打開 Binder 驅(qū)動、通過 mmap 映射內(nèi)存緩存,啟動 binder 線程池;
- App 進(jìn)程在 Binder 啟動后會創(chuàng)建一個 ApplicationThread 的 Binder 實體,通過ServerManager 獲取 AMS 的 Binder 代理,將 ApplicationThread 這個 Binder 傳遞給 AMS;
- AMS 收到 attach 后,保存 ApplicationThread 對象的 Binder 代理對象,以方便后續(xù)與 App 進(jìn)程進(jìn)行通信。AMS 發(fā)送 attachApplication 請求,該請求最后會在 App 所在進(jìn)程的 Binder 線程被執(zhí)行,然后構(gòu)建一個 Message 對象發(fā)送給主線程執(zhí)行 Application 對象的初始化;
- App 的主線程收到消息后,構(gòu)建 LoadedApk 對象,該對象存儲 App 的一些基本信息,緊接著創(chuàng)建 ContentImpl 對象,并且通過反射創(chuàng)建 Application 對象,接著調(diào)用其 attach 方法,傳入 ContentImpl 對象,最后調(diào)用其 onCreate 方法;
- 再回到 AMS 剛剛通知 App 創(chuàng)建 Application 的位置,AMS 在執(zhí)行完該事后,會立馬通知 App 啟動 launch類型的 Activity 以及一些 service、廣播等
- App 在收到啟動首頁 Activity 事件后,通過反射創(chuàng)建 Activity 對象,并且同時創(chuàng)建一個 ContentImpl 對象,接著執(zhí)行 Activity 的 onCreate 方法,設(shè)置布局文件;
- 接下來 onResume 方法中,通過 WMS 的 addView 方法,將 ViewRoot 中的視圖添加到 WMS 中,并且視圖樹會執(zhí)行 attachToWindow 回調(diào);
- ViewRootImpl 會通過 Choreographer 注冊 vsyn 信息,在下一個 vsyn 信號到來之后,會執(zhí)行 msasure、layout、draw ,在 draw 方法執(zhí)行完之后,其內(nèi)部通過 canvas 的 api 調(diào)用繪制指令,這些指令會被記錄下來,最后通過 RenderThread 線程進(jìn)行計算執(zhí)行,最終通過 GPU進(jìn)行渲染;
- 渲染的數(shù)據(jù)會放到 Surface 緩沖區(qū)中,SufaceFlinger 將所有的窗口對象的 Surface 數(shù)據(jù)區(qū)域進(jìn)行合成,并發(fā)送到屏幕的后緩沖區(qū)域;
- 下一個 vsync 信號到來之后,后緩沖區(qū)的圖像就會顯示到屏幕上;
到了這里,關(guān)于Android Framework 之 啟動流程的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!