你了解Android系統(tǒng)啟動(dòng)流程嗎?
A:當(dāng)按電源鍵觸發(fā)開機(jī),首先會從ROM中預(yù)定義的地方加載引導(dǎo)程序BootLoader到RAM中,并執(zhí)行Bootl oader程序啟動(dòng)Linux Kernel,然后啟動(dòng)用戶級別的第一個(gè)進(jìn)程: init 進(jìn)程。init 進(jìn)程會解析init.c 腳本做一些初始化工作,包括掛載文件系統(tǒng)鸽照、創(chuàng)建工作目錄以及啟動(dòng)系統(tǒng)服務(wù)進(jìn)程等,其中系統(tǒng)服務(wù)進(jìn)程包括Zygote、service manager. media 等赔蒲。在Zygote中會進(jìn)一步去啟動(dòng) system. server進(jìn)程,然后在system server進(jìn)程中會啟動(dòng)AMS良漱、WMS舞虱、PMS等服務(wù),等這些服務(wù)啟動(dòng)之后母市,AMS中就會打開Launcher應(yīng)用的home Activity, 最終就看到了手機(jī)的"桌面"矾兜。
面試官: system. server為什么要在Zygote中啟動(dòng),而不是由init直接啟動(dòng)呢?
A: Zygote作為-一個(gè)孵化器患久,可以提前加載一些資源椅寺, 這樣fork()時(shí)基于Copy-On-Write機(jī)制創(chuàng)建的其他進(jìn)程就能直接使用這些資源,而不用重新加載蒋失。比如system. server就可以直接使用Zygote中的JNI函數(shù)返帕、共享庫、常用的類篙挽、以及主題資源荆萤。面試官:為什么要專門使用Zygote進(jìn)程去孵化應(yīng)用進(jìn)程,而不是讓system. server去孵化呢?A:首先system server 相比Zygote多運(yùn)行了AMS铣卡、WMS 等服務(wù),這些對-一個(gè)應(yīng)用程序來說是不需要的链韭。另外進(jìn)程的fork()對多線程不友好,僅會將發(fā)起調(diào)用的線程拷貝到子進(jìn)程煮落,這可能會導(dǎo)致死鎖敞峭,而system. server中肯定是有很多線程的。
面試官:能說說具體是怎么導(dǎo)致死鎖的嗎?
在POSIX標(biāo)準(zhǔn)中州邢,fork 的行為是這樣的:復(fù)制整個(gè)用戶空間的數(shù)據(jù)(通常使用copy-on-write的策略儡陨,所以可以實(shí)現(xiàn)的速度很快)以及所有系統(tǒng)對象,然后僅復(fù)制當(dāng)前線程到子進(jìn)程量淌。這里:所有父進(jìn)程中別的線程骗村,到了子進(jìn)程中都是突然蒸發(fā)掉的
對于鎖來說,從OS看呀枢,每個(gè)鎖有一一個(gè)所有者胚股,即最后一-次lock它的線程。假設(shè)這么一 一個(gè)環(huán)境裙秋,在fork之前琅拌,有一一個(gè)子線程lock了某個(gè)鎖缨伊,獲得了對鎖的所有權(quán)。fork 以后进宝,在子進(jìn)程中刻坊,所有的額外線程都人間蒸發(fā)了。而鎖卻被正常復(fù)制了党晋,在子進(jìn)程看來谭胚,這個(gè)鎖沒有主人,所以沒有任何人可以對它解鎖未玻。當(dāng)子進(jìn)程想lock這個(gè)鎖時(shí)灾而,不再有任何手段可以解開了。程序發(fā)生死鎖
面試官: Zygote為什么不采用Binder機(jī)制進(jìn)行IPC通信?
A: Binder機(jī)制中存在Binder線程池扳剿,是多線程的旁趟,如果Zygote采用Binder的話就存在上面說的fork0與多線程的問題了。其實(shí)格來說Binder 機(jī)制不- -定要多線程庇绽, 所謂的Binder線程只不過是在循環(huán)讀取Binder驅(qū)動(dòng)的消息而已锡搜,只注冊一個(gè)Binder線程也是可以工作的,比如service manager就是這樣的敛劝。實(shí)際上Zygote盡管沒有采取Binder機(jī)制余爆,它也不是單線程的,但它在fork0前主動(dòng)停止了其他線程夸盟,fork0后重新啟動(dòng)了蛾方。