站長工具永久更新網(wǎng)址查詢工具
? ? ? ?當按下Android系統(tǒng)的開機電源按鍵時候,硬件會觸發(fā)引導芯片,執(zhí)行預定義的代碼,然后加載引導程序(BootLoader)到RAM,Bootloader是Android系統(tǒng)起來前第一個程序,主要用來拉起Android系統(tǒng)程序,Android系統(tǒng)被拉起首先肯定會啟動Linux內核。
備注: 我們再刷機時候,經(jīng)??吹焦ぞ哕浖屛覀兦袚Qbootloader/loader模式,其實就是重新激活bootloader程序,然后再拷貝新的鏡像文件重新刷機,就是通過這個程序重新初始化硬件設備,建立內存空間映射。
? ? ? ? 我們也知道一個系統(tǒng)肯定會存在一些重要服務和進程來支持整個系統(tǒng)正常運作。? 那么Android系統(tǒng)中肯定也存在這種重要進程,如下:??
序號 | 進程名稱 | 概述 |
1 | init進程 | Linux系統(tǒng)中用戶空間第一個進程 |
2 | zygote進程 | 所有App進程的父進程,Zygote Init? |
3 | system_server進程 | 各大系統(tǒng)服務的載體,forkSystemServer / SystemServer |
4 | servicemanager進程 | binder服務的大管家,守護進程循環(huán)運行在binder_loop? |
內核啟動首先會第一個創(chuàng)建init進程,進程號是1,是所有用戶空間的鼻祖,init進程又會啟動servicemanager(binder服務管家) 和zygote進程(Java進程鼻祖),zygote進程會創(chuàng)建system_server進程以及各種app進程,大致啟動關系如下:?
源碼分析:基于 android10?
inity源碼分析
/system/core/init/main.cpp??
int main(int argc, char** argv) {#if __has_feature(address_sanitizer)__asan_set_error_report_callback(AsanReportCallback);#endifif (!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ù)有四個參數(shù)入口:?
1.參數(shù)有ueventd進入 uevent_main??
2. 參數(shù)中有subcontext,進入InitLogging和 SubcontextMain?
3. 參數(shù)中有selinux_setup,進入SetupSelinux?
4. 參數(shù)中有second_state,進入SecondStageMain?
執(zhí)行順序如下: 首先會進入FirstStateMain ,主要執(zhí)行是初始化環(huán)境變量,掛載和創(chuàng)建基本的文件系統(tǒng),并設置訪問權限,掛載system、cache、data等系統(tǒng)分區(qū) 。 之后進入? 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主要工作誰設置SELinux安全策略,之后進入SecondStageMain?。??
int SecondStageMain(int argc, char** argv) {..... // oom_scroe_adj 為-1000時候相當與關閉OOM機制。 范圍 -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();// 設置所有進程都可以訪問的會話密鑰環(huán)keyctl_get_keyring_ID(KEY_SPEC_SESSION_KEYRING, 1);// 標記booting中 close(open("/dev/.booting", O_WRONLY | O_CREAT | O_CLOEXEC, 0000));//初始化屬性服務,指定文件讀取屬性property_init();....... // 為第二階段設置 SELinux。SelinuxSetupKernelLogging();SelabelInitialize();SelinuxRestoreContext();// android封裝好的Epoll開始初始化 Epoll epoll;if (auto result = epoll.Open(); !result) {PLOG(FATAL) << result.error();}// 注冊singelfd信號,為創(chuàng)建handler處理子進程終止信號 InstallSignalFdHandler(&epoll);..... // 注冊property_set_fd, 設置其他系統(tǒng)屬性并開啟系統(tǒng)屬性服務 StartPropertyService(&epoll);MountHandler mount_handler(&epoll);....... ActionManager& am = ActionManager::GetInstance();ServiceList& sm = ServiceList::GetInstance();//解析init.rc 等文件,建立rc文件的action,service,啟動其他進程。 LoadBootScripts(am, sm);..... am.QueueBuiltinAction(SetupCgroupsAction, "SetupCgroups");//rc文件中觸發(fā)器為 on earyly-init 語句 am.QueueEventTrigger("early-init");// 等待冷插拔設備初始化完成 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");// 設備組合鍵初始化操作 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");// 開始觸發(fā)rc文件中為 on init 的語句 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_doneam.QueueBuiltinAction(MixHwrngIntoLinuxRngAction, "MixHwrngIntoLinuxRng");// Initialize binder before bringing up other system servicesam.QueueBuiltinAction(InitBinder, "InitBinder");//不要在充電器模式下掛載文件系統(tǒng)或啟動核心系統(tǒng)服務。.std::string bootmode = GetProperty("ro.bootmode", "");if (bootmode == "charger") {am.QueueEventTrigger("charger");} else {am.QueueEventTrigger("late-init");} // 根據(jù)屬性的當前狀態(tài)運行所有屬性觸發(fā)器。.am.QueueBuiltinAction(queue_property_triggers_action, "queue_property_triggers");while (true) {//進入死循環(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();// 如果有一個進程需要重新啟動,請及時喚醒。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;}}// 如果還有更多工作要做,請立即醒來。if (am.HasMoreCommands()) epoll_timeout = 0ms;}// 這里一直等待循環(huán)事件 過來if (auto result = epoll.Wait(epoll_timeout); !result) {LOG(ERROR) << result.error();}}return 0;}
其中最關鍵就是解析init.rc 文件,并且按照rc文件定義去啟動服務,然后開啟死循環(huán),用于接受epoll事件??
init.rc文件
init.rc文件在?/system/core/rootdir/init.rc?
import /init.environ.rcimport /init.usb.rcimport /init.${ro.hardware}.rcimport /vendor/etc/init/hw/init.${ro.hardware}.rcimport /init.usb.configfs.rcimport /init.${ro.zygote}.rc
zygote服務啟動
Zygote是由init進程通過解析init.zygote.rc文件而創(chuàng)建
我們可以看到/system/core/rootdir/下有4個init.zygote.rc文件,通過ro.zygote配置得值去讀取對應配置文件,這里以init.zygote64.rc? 為例子?
service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-serverclass mainpriority -20user rootgroup root readproc reserved_disksocket zygote stream 660 root systemsocket usap_pool_primary stream 660 root systemonrestart write /sys/android_power/request_state wakeonrestart write /sys/power/state ononrestart restart audioserveronrestart restart cameraserveronrestart restart mediaonrestart restart netdonrestart restart wificondwritepid /dev/cpuset/foreground/tasks
對應的可執(zhí)行程序是app_process64 , 對應的源文件是/frameworks/base/cmds/app_process/app_main.cpp
zygote啟動過程如下:?
1.創(chuàng)建了AppRuntime,并且調用了start方法。?
2. AndroidRuntime調用了startVm創(chuàng)建了虛擬機,調用startReg注冊JNI函數(shù)。?
3.通過JNI調用ZygoteInit.main 進入Java? 。
4. 建立socket通道,zygote作為通訊服務端,用于響應客戶端請求。?
5. 預加載通用類,drawable,color資源,共享庫等,用于提高app啟動效率。?
6. forksytem_server進程,上層java framework的運行載體。?
參考文章:Android系統(tǒng)啟動-zygote篇 - Gityuan博客 | 袁輝輝的技術博客袁輝輝, Gityuan, Android博客, Android源碼, Flutter博客,Flutter源碼http://gityuan.com/2016/02/13/android-zygote/