歡迎大家前往騰訊雲+社區,獲取更多騰訊海量技術實踐干貨哦~
相信我們對Android系統都不陌生,而Android系統博大精深,被各種各樣的智能設備承載的同時,我們會否好奇過,如此復雜的Android究竟是怎么運作起來的呢?借本文給大家分享,筆者對Android 系統啟動流程的整體理解~
hi, I'm Android
現在,按下電源鍵
下面是Android啟動的核心步驟流程圖,看文字的時候,記得回來對照圖來理解喔,希望閱讀全文后,回觀流程圖,會有恍然大悟的感覺,那么文章的目的就達到啦~
整體流程
一、啟動電源及系統啟動
系統從 ROM 中開始啟動,加載引導程序到 RAM ,然后執行。
二、引導程序
引導程序是 Android 操作系統開始運行前的一個小程序,因此它需要針對特定主板與芯片,並不是 Android 操作系統的一部分。引導程序是 OEM 廠商或運行商進行加鎖、限制的地方。
1 兩個階段
- 檢測外部 RAM 以及為第二階段加載程序
- 設置網絡、內存等,搭建內核運行環境(為了達到特殊目的時,引導程序可以根據配置參數或者輸入數據來設置內核)
2 引導程序的加載器
Android引導程序可以在\bootable\bootloader\legacy\usbloader找到,傳統的加載器包含的兩個文件:
- init.s 初始化堆棧,清零BSS段,會調用 main.c 中的 _main()函數 (bss segment:通常是指用來存放程序中未初始化的全局變量的一塊內存區域;BSS - Block Started by Symbol。BSS段屬於靜態內存分配)
- main.c 初始化硬件,創建 linux 標簽
三、內核啟動
Android 內核啟動方式類似桌面 linux,主要步驟:
1. 設置緩存
2. 被保護存儲器
3. 計划列表
4. 加載驅動
當內核完成系統設置,接下來即將啟動系統的第一個進程 -- init 進程
四、init 進程
作為 Android 系統的第一個進程,其PID為0,通過解析 init.rc 腳本來構建出系統初始運行形態,這一階段中,“Android” logo 會顯示出來
(系統中,大多數系統服務程序都是在該腳本中描述並被相繼啟動的)
init.rc 由4種類型聲明組成:Actions、Commands、Services、Options
- Actions:響應某事件的過程。當“trigger”所描述的觸發事件產生時,則依次執行各種“command” 源碼角度:系統會對 init.rc 中各“trigger”進行匹配,當發現符合條件的 Action,就將它加入“命令執行隊列”尾部(除非 Action 已存在隊列中),然后系統再對這些命令按順序進行。on
##觸發條件 ##執行命令 ##可執行多個命令 ... - Commands:命令將在所屬事件發生時被一個個執行
- Services:可執行程序,它們在特定選項的約束下會被 init 程序運行或者重啟(Service 可以在配置中指定是否需要退出重啟,那么,當 Service 出現異常 crash 時,可有機會復原)service
[ ]* - Options:對 service 的約束選項
五和六、 ServiceManager、Zygote、SystemServer
科普:Daemons - 守護進程
init進程通過解析 init.rc 來陸續啟動其他關鍵的系統服務進程,其中最重要的是 ServiceManager、Zygote 和 SystemServer 三者,下面我們逐一解析:
1 ServiceManager -- Binder 機制支撐者
概述:ServiceManager 是 Binder 機制中的支撐者,負責某 Binder 服務注冊信息到底層 Binder 驅動分配的值解析。
ServiceManager 由 init 進程解析 rc 腳本時啟動,屬於 core 類,其他同類進程包括:uenetd、console、adbd等。根據 core 組的特性,這些進程會同時啟動或停止。另外,ServiceManager 配置含有 critical 屬性,這意味着它是系統關鍵進程(如果進程不幸在4分鍾內異常退出超過4次,設備將重啟並進入還原模式)。當 ServiceManager 每次重啟時,其他關鍵進程:zygote、media、surfaceflinger 等也會被 restart。
2. Zygote -- “孕育”新線程與進程
Android 中大多數應用進程與系統進程都是通過 Zygote 來生成的。Zygote 同樣由 init 解析 rc 腳本時啟動,屬於 main 類,同屬 main 類的系統進程有:netd、debuggerd、rild等。Zygote並不是處於獨立的程序中的,它所在程序名為“app_process”,觀察 app_process 主函數實現知道,如果 init.rc 中指定了 --zygote選項,app_process 接下來將啟動“ZygoteInit”,並傳入“start-system-server”,這樣,ZygoteInit 就會運行在虛擬機上(Dalvik VM)上了。
-
ZygoteInit 函數有兩項重要工作
-
預裝載各種系統類
-
搭建 SystemServer 環境,並啟動 SystemServer(大部分的 Android 系統服務都在其中,由 Java 編寫)
-
ZygoteInit 流程總結
(
摘自:Gityuan -- Android 系統啟動-Zygote 篇
)
- 解析init.zygote.rc中的參數,創建AppRuntime並調用AppRuntime.start()方法;
- 調用AndroidRuntime的startVM()方法創建虛擬機,再調用startReg()注冊JNI函數;
- 通過JNI方式調用ZygoteInit.main(),第一次進入Java世界;
- registerZygoteSocket()建立socket通道,zygote作為通信的服務端,用於響應客戶端請求;
- preload()預加載通用類、drawable和color資源、openGL以及共享庫以及WebView,用於提高ap啟動效率;
- zygote完畢大部分工作,接下來再通過startSystemServer(),fork得力幫手system_server進程,也是上層framework的運行載體。
- zygote功成身退,調用runSelectLoop(),隨時待命,當接收到請求創建新進程請求時立即喚醒並執行相應工作。
ZygoteInit 結束后,開機Logo就出來了。
(注意:這里並不包括開機動畫,而是開機前 “Android” Logo 出現的那個畫面,開機動畫出現之前還需要進行各種加載,開機動畫是在“Android” Logo 出現之后才播放的)
3. SystemServer -- 大部分 Android 系統服務所在地
SystemServer 是 Android 進入 Launcher 前的最后准備,它提供了眾多的由“Java”語言編寫的系統服務。
如果 init.rc 中為 zygote 指定啟動參數 --start-system-server,那么 ZygotyeInit 就會調用 startSystemServer 來進入 SystemServer。
- startSystemServer函數解析:
- 首先 ZygoteInit 通過 Zygote.forkSystemServer 來生成一個新的線程(fork),用於承載各種系統服務。(源碼角度:Zygote 內部由 Native 函數 Dalvik_dalvik_system_Zygote_forkSystemServer 來進一步實現,最終調用底層接口的 fork 接口來實際產生進程)
- 根據fork特性,子進程與父進程將獲得相同的代碼環境。pid為0為子進程,否則為父進程;如果是前者,則進一步調用 handleSystemServerProcess(parseArgs) 函數來完成最核心的工作 -- “啟動各系統服務”(源碼角度:handleSystemServerProcess 方法將 startSystemServer 中的 parsedArgs.remainingArgs 參數傳給 RuntimeInit.zygoteInit,后者又調用 nativeZygoteInit 函數)
- nativeZygoteInit 調用后,接着,三個重要的 static 函數就要被執行了:init1 - 完成本地Service(SurfaceFlinger、AudioFlinger等)啟動,完成后調用 init2、init2 - 新建一個新的帶 Looper 的線程 ServerThread來啟動 Java層各 Service
后語
上面對 Android 系統啟動做了一個簡述,意在給大家展現一個整體流程,其中每個環節涉及的知識點只是淺淺掠過,筆者也尚在學習與探索中,希望在后續再作詳細分析。
資源推薦
- Gityuan - Android 開篇
- 老羅的Android之旅
- 《深入理解 Android 內核設計思想》 由淺入深,落實到源碼層面上進行探索,知識很有深度
此文已由作者授權騰訊雲+社區發布,更多原文請點擊
搜索關注公眾號「雲加社區」,第一時間獲取技術干貨,關注后回復1024 送你一份技術課程大禮包!
海量技術實踐經驗,盡在雲加社區!