? ? ? ?當(dāng)按下Android系統(tǒng)的開(kāi)機(jī)電源按鍵時(shí)候,硬件會(huì)觸發(fā)引導(dǎo)芯片,執(zhí)行預(yù)定義的代碼,然后加載引導(dǎo)程序(BootLoader)到RAM,Bootloader是Android系統(tǒng)起來(lái)前第一個(gè)程序,主要用來(lái)拉起Android系統(tǒng)程序,Android系統(tǒng)被拉起首先肯定會(huì)啟動(dòng)Linux內(nèi)核。
備注: 我們?cè)偎C(jī)時(shí)候,經(jīng)常看到工具軟件會(huì)讓我們切換bootloader/loader模式,其實(shí)就是重新激活bootloader程序,然后再拷貝新的鏡像文件重新刷機(jī),就是通過(guò)這個(gè)程序重新初始化硬件設(shè)備,建立內(nèi)存空間映射。
? ? ? ? 我們也知道一個(gè)系統(tǒng)肯定會(huì)存在一些重要服務(wù)和進(jìn)程來(lái)支持整個(gè)系統(tǒng)正常運(yùn)作。? 那么Android系統(tǒng)中肯定也存在這種重要進(jìn)程,如下:??
序號(hào) | 進(jìn)程名稱(chēng) | 概述 |
1 | init進(jìn)程 | Linux系統(tǒng)中用戶(hù)空間第一個(gè)進(jìn)程 |
2 | zygote進(jìn)程 | 所有App進(jìn)程的父進(jìn)程,Zygote Init? |
3 | system_server進(jìn)程 | 各大系統(tǒng)服務(wù)的載體,forkSystemServer / SystemServer |
4 | servicemanager進(jìn)程 | binder服務(wù)的大管家,守護(hù)進(jìn)程循環(huán)運(yùn)行在binder_loop? |
內(nèi)核啟動(dòng)首先會(huì)第一個(gè)創(chuàng)建init進(jìn)程,進(jìn)程號(hào)是1,是所有用戶(hù)空間的鼻祖,init進(jìn)程又會(huì)啟動(dòng)servicemanager(binder服務(wù)管家) 和zygote進(jìn)程(Java進(jìn)程鼻祖),zygote進(jìn)程會(huì)創(chuàng)建system_server進(jìn)程以及各種app進(jìn)程,大致啟動(dòng)關(guān)系如下:?
源碼分析:基于 android10?
inity源碼分析
/system/core/init/main.cpp??
int main(int argc, char** argv) {
#if __has_feature(address_sanitizer)
__asan_set_error_report_callback(AsanReportCallback);
#endif
if (!strcmp(basename(argv[0]), "ueventd")) {
return ueventd_main(argc, argv);
}
if (argc > 1) {
if (!strcmp(argv[1], "subcontext")) {
android::base::InitLogging(argv, &android::base::KernelLogger);
const BuiltinFunctionMap function_map;
return SubcontextMain(argc, argv, &function_map);
}
if (!strcmp(argv[1], "selinux_setup")) {
return SetupSelinux(argv);
}
if (!strcmp(argv[1], "second_stage")) {
return SecondStageMain(argc, argv);
}
}
return FirstStageMain(argc, argv);
}
main函數(shù)有四個(gè)參數(shù)入口:?
1.參數(shù)有ueventd進(jìn)入 uevent_main??
2. 參數(shù)中有subcontext,進(jìn)入InitLogging和 SubcontextMain?
3. 參數(shù)中有selinux_setup,進(jìn)入SetupSelinux?
4. 參數(shù)中有second_state,進(jìn)入SecondStageMain?
執(zhí)行順序如下: 首先會(huì)進(jìn)入FirstStateMain ,主要執(zhí)行是初始化環(huán)境變量,掛載和創(chuàng)建基本的文件系統(tǒng),并設(shè)置訪(fǎng)問(wèn)權(quán)限,掛載system、cache、data等系統(tǒng)分區(qū) 。 之后進(jìn)入? SetupSelinxu 根據(jù)源碼我們可以看到FirstStateMain最后傳送了參數(shù)selinux_setup?
int FirstStageMain(int argc, char** argv) {
.......
const char* path = "/system/bin/init";
const char* args[] = {path, "selinux_setup", nullptr};
execv(path, const_cast<char**>(args));
// execv() only returns if an error happened, in which case we
// panic and never fall through this conditional.
PLOG(FATAL) << "execv(\"" << path << "\") failed";
return 1;
}
SetupSelinux主要工作誰(shuí)設(shè)置SELinux安全策略,之后進(jìn)入SecondStageMain?。??
int SecondStageMain(int argc, char** argv) {
.....
// oom_scroe_adj 為-1000時(shí)候相當(dāng)與關(guān)閉OOM機(jī)制。 范圍 -1000 - 1000
if (auto result = WriteFile("/proc/1/oom_score_adj", "-1000"); !result) {
LOG(ERROR) << "Unable to write -1000 to /proc/1/oom_score_adj: " << result.error();
}
// 啟用全局Seccomp
GlobalSeccomp();
// 設(shè)置所有進(jìn)程都可以訪(fǎng)問(wèn)的會(huì)話(huà)密鑰環(huán)
keyctl_get_keyring_ID(KEY_SPEC_SESSION_KEYRING, 1);
// 標(biāo)記booting中
close(open("/dev/.booting", O_WRONLY | O_CREAT | O_CLOEXEC, 0000));
//初始化屬性服務(wù),指定文件讀取屬性
property_init();
.......
// 為第二階段設(shè)置 SELinux。
SelinuxSetupKernelLogging();
SelabelInitialize();
SelinuxRestoreContext();
// android封裝好的Epoll開(kāi)始初始化
Epoll epoll;
if (auto result = epoll.Open(); !result) {
PLOG(FATAL) << result.error();
}
// 注冊(cè)singelfd信號(hào),為創(chuàng)建handler處理子進(jìn)程終止信號(hào)
InstallSignalFdHandler(&epoll);
.....
// 注冊(cè)property_set_fd, 設(shè)置其他系統(tǒng)屬性并開(kāi)啟系統(tǒng)屬性服務(wù)
StartPropertyService(&epoll);
MountHandler mount_handler(&epoll);
.......
ActionManager& am = ActionManager::GetInstance();
ServiceList& sm = ServiceList::GetInstance();
//解析init.rc 等文件,建立rc文件的action,service,啟動(dòng)其他進(jìn)程。
LoadBootScripts(am, sm);
.....
am.QueueBuiltinAction(SetupCgroupsAction, "SetupCgroups");
//rc文件中觸發(fā)器為 on earyly-init 語(yǔ)句
am.QueueEventTrigger("early-init");
// 等待冷插拔設(shè)備初始化完成
am.QueueBuiltinAction(wait_for_coldboot_done_action,"wait_for_coldboot_done");
// so that we can start queuing up actions that require stuff from /dev.
am.QueueBuiltinAction(MixHwrngIntoLinuxRngAction, "MixHwrngIntoLinuxRng");
am.QueueBuiltinAction(SetMmapRndBitsAction, "SetMmapRndBits");
am.QueueBuiltinAction(SetKptrRestrictAction, "SetKptrRestrict");
// 設(shè)備組合鍵初始化操作
Keychords keychords;
am.QueueBuiltinAction(
[&epoll, &keychords](const BuiltinArguments& args) -> Result<Success> {
for (const auto& svc : ServiceList::GetInstance()) {
keychords.Register(svc->keycodes());
}
keychords.Start(&epoll, HandleKeychord);
return Success();
},
"KeychordInit");
am.QueueBuiltinAction(console_init_action, "console_init");
// 開(kāi)始觸發(fā)rc文件中為 on init 的語(yǔ)句
am.QueueEventTrigger("init");
// Starting the BoringSSL self test, for NIAP certification compliance.
am.QueueBuiltinAction(StartBoringSslSelfTest, "StartBoringSslSelfTest");
// Repeat mix_hwrng_into_linux_rng in case /dev/hw_random or /dev/random
// wasn't ready immediately after wait_for_coldboot_done
am.QueueBuiltinAction(MixHwrngIntoLinuxRngAction, "MixHwrngIntoLinuxRng");
// Initialize binder before bringing up other system services
am.QueueBuiltinAction(InitBinder, "InitBinder");
//不要在充電器模式下掛載文件系統(tǒng)或啟動(dòng)核心系統(tǒng)服務(wù)。.
std::string bootmode = GetProperty("ro.bootmode", "");
if (bootmode == "charger") {
am.QueueEventTrigger("charger");
} else {
am.QueueEventTrigger("late-init");
}
// 根據(jù)屬性的當(dāng)前狀態(tài)運(yùn)行所有屬性觸發(fā)器。.
am.QueueBuiltinAction(queue_property_triggers_action, "queue_property_triggers");
while (true) {
//進(jìn)入死循環(huán)s.
auto epoll_timeout = std::optional<std::chrono::milliseconds>{};
if (do_shutdown && !shutting_down) {
do_shutdown = false;
if (HandlePowerctlMessage(shutdown_command)) {
shutting_down = true;
}
}
if (!(waiting_for_prop || Service::is_exec_service_running())) {
am.ExecuteOneCommand();
}
if (!(waiting_for_prop || Service::is_exec_service_running())) {
if (!shutting_down) {
auto next_process_action_time = HandleProcessActions();
// 如果有一個(gè)進(jìn)程需要重新啟動(dòng),請(qǐng)及時(shí)喚醒。
if (next_process_action_time) {
epoll_timeout = std::chrono::ceil<std::chrono::milliseconds>(
*next_process_action_time - boot_clock::now());
if (*epoll_timeout < 0ms) epoll_timeout = 0ms;
}
}
// 如果還有更多工作要做,請(qǐng)立即醒來(lái)。
if (am.HasMoreCommands()) epoll_timeout = 0ms;
}
// 這里一直等待循環(huán)事件 過(guò)來(lái)
if (auto result = epoll.Wait(epoll_timeout); !result) {
LOG(ERROR) << result.error();
}
}
return 0;
}
其中最關(guān)鍵就是解析init.rc 文件,并且按照rc文件定義去啟動(dòng)服務(wù),然后開(kāi)啟死循環(huán),用于接受epoll事件??
init.rc文件
init.rc文件在?/system/core/rootdir/init.rc?
import /init.environ.rc
import /init.usb.rc
import /init.${ro.hardware}.rc
import /vendor/etc/init/hw/init.${ro.hardware}.rc
import /init.usb.configfs.rc
import /init.${ro.zygote}.rc
zygote服務(wù)啟動(dòng)
Zygote是由init進(jìn)程通過(guò)解析init.zygote.rc文件而創(chuàng)建
我們可以看到/system/core/rootdir/下有4個(gè)init.zygote.rc文件,通過(guò)ro.zygote配置得值去讀取對(duì)應(yīng)配置文件,這里以init.zygote64.rc? 為例子?
service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server
class main
priority -20
user root
group root readproc reserved_disk
socket zygote stream 660 root system
socket usap_pool_primary stream 660 root system
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart audioserver
onrestart restart cameraserver
onrestart restart media
onrestart restart netd
onrestart restart wificond
writepid /dev/cpuset/foreground/tasks
對(duì)應(yīng)的可執(zhí)行程序是app_process64 , 對(duì)應(yīng)的源文件是/frameworks/base/cmds/app_process/app_main.cpp
zygote啟動(dòng)過(guò)程如下:?
1.創(chuàng)建了AppRuntime,并且調(diào)用了start方法。?
2. AndroidRuntime調(diào)用了startVm創(chuàng)建了虛擬機(jī),調(diào)用startReg注冊(cè)JNI函數(shù)。?
3.通過(guò)JNI調(diào)用ZygoteInit.main 進(jìn)入Java? 。
4. 建立socket通道,zygote作為通訊服務(wù)端,用于響應(yīng)客戶(hù)端請(qǐng)求。?
5. 預(yù)加載通用類(lèi),drawable,color資源,共享庫(kù)等,用于提高app啟動(dòng)效率。?
6. forksytem_server進(jìn)程,上層java framework的運(yùn)行載體。?文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-551428.html
參考文章:Android系統(tǒng)啟動(dòng)-zygote篇 - Gityuan博客 | 袁輝輝的技術(shù)博客袁輝輝, Gityuan, Android博客, Android源碼, Flutter博客,F(xiàn)lutter源碼http://gityuan.com/2016/02/13/android-zygote/文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-551428.html
到了這里,關(guān)于Android系統(tǒng)啟動(dòng)流程分析的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!