Android啟動(dòng)流程
第一步:?jiǎn)?dòng)電源以及系統(tǒng)啟動(dòng)
當(dāng)電源按下,引導(dǎo)芯片代碼開(kāi)始從預(yù)定義的地方(固化在ROM)開(kāi)始執(zhí)行。加載引導(dǎo)程序到RAM,然后 執(zhí)行
第二步:引導(dǎo)程序
引導(dǎo)程序是在Android操作系統(tǒng)開(kāi)始運(yùn)行前的一個(gè)小程序。引導(dǎo)程序是運(yùn)行的第一個(gè)程序,因此它是針 對(duì)特定的主板與芯片的。設(shè)備制造商要么使用很受歡迎的引導(dǎo)程序比如redboot、uboot、qi bootloader或者開(kāi)發(fā)自己的引導(dǎo)程序,它不是Android操作系統(tǒng)的一部分。引導(dǎo)程序是OEM廠商或者運(yùn) 營(yíng)商加鎖和限制的地方。
引導(dǎo)程序分兩個(gè)階段執(zhí)行。
第一個(gè)階段,檢測(cè)外部的RAM以及加載對(duì)第二階段有用的程序; 第二階段,引導(dǎo)程序設(shè)置網(wǎng)絡(luò)、內(nèi)存等等。這些對(duì)于運(yùn)行內(nèi)核是必要的,為了達(dá)到特殊的目標(biāo),引導(dǎo)程 序可以根據(jù)配置參數(shù)或者輸入數(shù)據(jù)設(shè)置內(nèi)核。 Android引導(dǎo)程序可以在\bootable\bootloader\legacy\usbloader找到。傳統(tǒng)的加載器包含兩個(gè)文件, 需要在這里說(shuō)明:
init.s初始化堆棧,清零BBS段,調(diào)用main.c的_main()函數(shù); main.c初始化硬件(鬧鐘、主板、鍵盤(pán)、控制臺(tái)),創(chuàng)建linux標(biāo)簽
第三步:內(nèi)核
Android內(nèi)核與桌面linux內(nèi)核啟動(dòng)的方式差不多。內(nèi)核啟動(dòng)時(shí),設(shè)置緩存、被保護(hù)存儲(chǔ)器、計(jì)劃列表, 加載驅(qū)動(dòng)。當(dāng)內(nèi)核完成系統(tǒng)設(shè)置,它首先在系統(tǒng)文件中尋找”init”文件,然后啟動(dòng)root進(jìn)程或者系統(tǒng)的第 一個(gè)進(jìn)程
第四步:init進(jìn)程 (搭建環(huán)境+啟動(dòng)zygote)
init進(jìn)程是Linux系統(tǒng)中用戶空間的第一個(gè)進(jìn)程,進(jìn)程號(hào)固定為1。Kernel啟動(dòng)后,在用戶空間啟動(dòng)init進(jìn)程,并調(diào)用init中的main()方法執(zhí)行init進(jìn)程的職責(zé)。
- 創(chuàng)建和掛載啟動(dòng)所需的文件目錄
- 初始化和啟動(dòng)屬性服務(wù)
- 解析init.rc配置文件并 啟動(dòng)zygote進(jìn)程
3.1 ----》SystemServers—》開(kāi)啟一系列服務(wù)(AMS、WMS、PKMS、PMS、、、、)
3.2 ----》Launcher --> app —> 從 zygote fork 子進(jìn)程 app
第五步:?jiǎn)?dòng)Lancher App
fork函數(shù)
pid_t fork(void)
返回值分兩種情況:
- 返回0表示成功創(chuàng)建子進(jìn)程,并且接下來(lái)進(jìn)入子進(jìn)程執(zhí)行流程
- 返回PID(>0),成功創(chuàng)建子進(jìn)程,并且繼續(xù)執(zhí)行父進(jìn)程流程代碼
- 返回非正數(shù)(<0),創(chuàng)建子進(jìn)程失敗,失敗原因主要有: 進(jìn)程數(shù)超過(guò)系統(tǒng)所能創(chuàng)建的上限,errno會(huì)被設(shè)置為EAGAIN系統(tǒng)內(nèi)存不足,errno會(huì)被設(shè)置為 ENOMEM
使用 fork() 函數(shù)得到的子進(jìn)程是父進(jìn)程的一個(gè)復(fù)制品,它從父進(jìn)程處繼承了整個(gè)進(jìn)程的地址空 間:包括進(jìn)程上下文(進(jìn)程執(zhí)行活動(dòng)全過(guò)程的靜態(tài)描述)、進(jìn)程堆棧、打開(kāi)的文件描述符、信號(hào)控 制設(shè)定、進(jìn)程優(yōu)先級(jí)、進(jìn)程組號(hào)等。子進(jìn)程所獨(dú)有的只有它的進(jìn)程號(hào),計(jì)時(shí)器等(只有小量信 息)。因此,使用 fork() 函數(shù)的代價(jià)是很大的
子進(jìn)程與父進(jìn)程的區(qū)別:
- 除了文件鎖以外,其他的鎖都會(huì)被繼承
- 各自的進(jìn)程ID和父進(jìn)程ID不同
- 子進(jìn)程的未決告警被清除;
- 子進(jìn)程的未決信號(hào)集設(shè)置為空集。
相關(guān)面試題
你了解Android啟動(dòng)流程嗎
當(dāng)按電源鍵觸發(fā)開(kāi)機(jī),首先會(huì)從ROM中預(yù)定義的地方加載引導(dǎo)程序BootLoader到RAM中,并執(zhí)行BootLoader程序啟動(dòng)Linux kernel,然后啟動(dòng)用戶級(jí)別的第一個(gè)進(jìn)程:init進(jìn)程。init進(jìn)程會(huì)解析init.rc腳本并做一些初始化工作,包括掛載文件系統(tǒng)、創(chuàng)建工作目錄以及啟動(dòng)系統(tǒng)服務(wù)進(jìn)程等,其中系統(tǒng)服務(wù)進(jìn)程包括Zygote、system manger、media等。在zygote中會(huì)進(jìn)一步啟動(dòng)system_server進(jìn)程,并啟動(dòng)AMS、WMS、PMS等服務(wù),等這些服務(wù)啟動(dòng)后AMS就會(huì)打開(kāi)Launcher應(yīng)用的home activity,然后看到了手機(jī)的“桌面”
system_server為什么要在zygote中啟動(dòng),而不是由init啟動(dòng)
zygote作為孵化器可以提前加載一些資源,這樣fork()時(shí)基于Copy_On_Write 機(jī)制創(chuàng)建的其他進(jìn)程就能直接使用這些資源而不用重新加載。比如system_server可以直接使用Zygote中的JNI函數(shù)、共享庫(kù)、常用的類、以及主題資源文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-414805.html
zygote為什么不用Binder機(jī)制進(jìn)行IPC通信
Binder 機(jī)制中存在 Binder 線程池,是多線程的,如果 Zygote 采用 Binder 的話就存在上面說(shuō)的fork() 與 多線程的問(wèn)題了。其實(shí)嚴(yán)格來(lái)說(shuō),Binder 機(jī)制不一定要多線程,所謂的 Binder 線程只不過(guò)是在循環(huán)讀取 Binder 驅(qū)動(dòng)的消息而已,只注冊(cè)一個(gè) Binder 線程也是可以工作的,比如 service manager就是這樣的。實(shí)際上 Zygote 盡管沒(méi)有采取 Binder 機(jī)制,它也不是單線程的,但它在 fork() 前主動(dòng)停止了其他線程,fork() 后重新啟動(dòng)了。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-414805.html
到了這里,關(guān)于Android:?jiǎn)?dòng)流程的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!