系统进程启动流程分析(一)
Android啟動概覽
眾所周知,Android是谷歌開發的一款基于Linux的開源操作系統,下圖所示為 Android 平臺的主要組件
1. Linux 內核
Android 平臺的基礎是 Linux 內核。例如,Android Runtime (ART) 依靠 Linux 內核來執行底層功
能,例如線程和低層內存管理。
使用 Linux 內核可讓 Android 利用主要安全功能,并且允許設備制造商為著名的內核開發硬件驅動程
序。
2. 硬件抽象層 (HAL)
硬件抽象層 (HAL) 提供標準界面,向更高級別的 Java API 框架顯示設備硬件功能。HAL 包含多個
庫模塊,其中每個模塊都為特定類型的硬件組件實現一個界面,例如相機或藍牙模塊。當框架 API
要求訪問設備硬件時,Android 系統將為該硬件組件加載庫模塊。
3. Android Runtime
對于運行 Android 5.0(API 級別 21)或更高版本的設備,每個應用都在其自己的進程中運行,并
且有其自己的 Android Runtime (ART) 實例。ART 編寫為通過執行 DEX 文件在低內存設備上運行
多個虛擬機,DEX 文件是一種專為 Android 設計的字節碼格式,經過優化,使用的內存很少。編
譯工具鏈(例如 Jack)將 Java 源代碼編譯為 DEX 字節碼,使其可在 Android 平臺上運行。
ART 的部分主要功能包括:
預先 (AOT) 和即時 (JIT) 編譯
優化的垃圾回收 (GC)
在 Android 9(API 級別 28)及更高版本的系統中,支持將應用軟件包中的 Dalvik Executable 格
式 (DEX) 文件轉換為更緊湊的機器代碼。
更好的調試支持,包括專用采樣分析器、詳細的診斷異常和崩潰報告,并且能夠設置觀察點以監控
特定字段
在 Android 版本 5.0(API 級別 21)之前,Dalvik 是 Android Runtime。如果您的應用在 ART 上
運行效果很好,那么它應該也可在 Dalvik 上運行,但反過來不一定。
Android 還包含一套核心運行時庫,可提供 Java API 框架所使用的 Java 編程語言中的大部分功能,包括
一些 Java 8 語言功能。
4. 原生 C/C++ 庫
許多核心 Android 系統組件和服務(例如 ART 和 HAL)構建自原生代碼,需要以 C 和 C++ 編寫的
原生庫。Android 平臺提供 Java 框架 API 以向應用顯示其中部分原生庫的功能。例如,您可以通
過 Android 框架的 Java OpenGL API 訪問 OpenGL ES,以支持在應用中繪制和操作 2D 和 3D 圖形。
如果開發的是需要 C 或 C++ 代碼的應用,可以使用 Android NDK 直接從原生代碼訪問某些原生平臺庫。
5. Java API 框架
您可通過以 Java 語言編寫的 API 使用 Android OS 的整個功能集。這些 API 形成創建 Android 應
用所需的構建塊,它們可簡化核心模塊化系統組件和服務的重復使用,包括以下組件和服務:
豐富、可擴展的視圖系統,可用以構建應用的 UI,包括列表、網格、文本框、按鈕甚至可嵌入的網
絡瀏覽器
資源管理器,用于訪問非代碼資源,例如本地化的字符串、圖形和布局文件
通知管理器,可讓所有應用在狀態欄中顯示自定義提醒
Activity 管理器,用于管理應用的生命周期,提供常見的導航返回棧
內容提供程序,可讓應用訪問其他應用(例如“聯系人”應用)中的數據或者共享其自己的數據
開發者可以完全訪問 Android 系統應用使用的框架 API。
6. 系統應用
Android 隨附一套用于電子郵件、短信、日歷、互聯網瀏覽和聯系人等的核心應用。平臺隨附的應
用與用戶可以選擇安裝的應用一樣,沒有特殊狀態。因此第三方應用可成為用戶的默認網絡瀏覽
器、短信 Messenger 甚至默認鍵盤(有一些例外,例如系統的“設置”應用)。
系統應用可用作用戶的應用,以及提供開發者可從其自己的應用訪問的主要功能。例如,如果您的應用
要發短信,您無需自己構建該功能,可以改為調用已安裝的短信應用向您指定的接收者發送消息。
接下來,我們來看下Android系統啟動的大概流程,如下圖所示:
第一步: 啟動電源以及系統啟動
當電源按下,引導芯片代碼開始從預定義的地方(固化在ROM)開始執行。加載引導程序到RAM,然后
執行
第二步:引導程序
引導程序是在Android操作系統開始運行前的一個小程序。引導程序是運行的第一個程序,因此它是針
對特定的主板與芯片的。設備制造商要么使用很受歡迎的引導程序比如redboot、uboot、qi
bootloader或者開發自己的引導程序,它不是Android操作系統的一部分。引導程序是OEM廠商或者運
營商加鎖和限制的地方。
引導程序分兩個階段執行。
第一個階段,檢測外部的RAM以及加載對第二階段有用的程序;
第二階段,引導程序設置網絡、內存等等。這些對于運行內核是必要的,為了達到特殊的目標,引導程
序可以根據配置參數或者輸入數據設置內核。
Android引導程序可以在\bootable\bootloader\legacy\usbloader找到。傳統的加載器包含兩個文件,
需要在這里說明:
init.s初始化堆棧,清零BBS段,調用main.c的_main()函數;
main.c初始化硬件(鬧鐘、主板、鍵盤、控制臺),創建linux標簽
第三步:內核
Android內核與桌面linux內核啟動的方式差不多。內核啟動時,設置緩存、被保護存儲器、計劃列表,
加載驅動。當內核完成系統設置,它首先在系統文件中尋找”init”文件,然后啟動root進程或者系統的第
一個進程
第四步:init進程
init進程是Linux系統中用戶空間的第一個進程,進程號固定為1。Kernel啟動后,在用戶空間啟動init進
程,并調用init中的main()方法執行init進程的職責。
第五步:啟動Lancher App
init進程分析
其中init進程是Android系統中及其重要的第一個進程,接下來我們來看下init進程注意做了些什么
1. 創建和掛載啟動所需要的文件目錄
2. 初始化和啟動屬性服務
3. 解析init.rc配置文件并啟動Zygote進程
init.rc解析
init.rc是一個非常重要的配置文件,它是由Android初始化語言(Android Init Language)編寫的腳
本,它主要包含五種類型語句:Action(Action中包含了一系列的Command)、Commands(init語言
中的命令)、Services(由init進程啟動的服務)、Options(對服務進行配置的選項)和Import(引入
其他配置文件)。init.rc的配置代碼如下所示。
Action
Action: 通過觸發器trigger,即以on開頭的語句來決定執行相應的service的時機,具體有如下時機:
- on early-init; 在初始化早期階段觸發;
- on init; 在初始化階段觸發;
- on late-init; 在初始化晚期階段觸發;
- on boot/charger: 當系統啟動/充電時觸發,還包含其他情況,此處不一一列舉;
- on property:=: 當屬性值滿足條件時觸發
Service
服務Service,以 service開頭,由init進程啟動,一般運行在init的一個子進程,所以啟動service前需要
判斷對應的可執行文件是否存在。init生成的子進程,定義在rc文件,其中每一個service在啟動時會通過
fork方式生成子進程。
例如: ?service servicemanager /system/bin/servicemanager 代表的是服務名為
servicemanager,服務執行的路徑為/system/bin/servicemanager。
Command
下面列舉常用的命令
- class_start <service_class_name>: 啟動屬于同一個class的所有服務;
- start <service_name>: 啟動指定的服務,若已啟動則跳過;
- stop <service_name>: 停止正在運行的服務
- setprop :設置屬性值
- mkdir :創建指定目錄
- symlink <sym_link>: 創建連接到的<sym_link>符號鏈接;
- write : 向文件path中寫入字符串;
- exec: fork并執行,會阻塞init進程直到程序完畢;
- exprot :設定環境變量;
- loglevel :設置log級別
Options
Options是Service的可選項,與service配合使用
- disabled: 不隨class自動啟動,只有根據service名才啟動;
- oneshot: service退出后不再重啟;
- user/group: 設置執行服務的用戶/用戶組,默認都是root;
- class:設置所屬的類名,當所屬類啟動/退出時,服務也啟動/停止,默認為default;
- onrestart:當服務重啟時執行相應命令;
- socket: 創建名為 /dev/socket/<name> 的socket
- critical: 在規定時間內該service不斷重啟,則系統會重啟并進入恢復模式
default: 意味著disabled=false,oneshot=false,critical=false。
service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote -- start-system-serverclass mainpriority -20user rootgroup root readproc reserved_disksocket zygote 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/tasksservice解析流程
// \system\core\init\init.cpp LoadBootScripts() L110 static void LoadBootScripts(ActionManager& action_manager, ServiceList& service_list) {Parser parser = CreateParser(action_manager, service_list);//創建解析器std::string bootscript = GetProperty("ro.boot.init_rc", "");if (bootscript.empty()) {parser.ParseConfig("/init.rc");if (!parser.ParseConfig("/system/etc/init")) {late_import_paths.emplace_back("/system/etc/init");}if (!parser.ParseConfig("/product/etc/init")) {late_import_paths.emplace_back("/product/etc/init");}if (!parser.ParseConfig("/odm/etc/init")) {late_import_paths.emplace_back("/odm/etc/init");}if (!parser.ParseConfig("/vendor/etc/init")) {late_import_paths.emplace_back("/vendor/etc/init");}} else {parser.ParseConfig(bootscript);//開始解析} // \system\core\init\init.cpp CreateParser() L100 Parser CreateParser(ActionManager& action_manager, ServiceList& service_list) {Parser parser;parser.AddSectionParser("service", std::make_unique<ServiceParser> (&service_list, subcontexts));//service解析parser.AddSectionParser("on", std::make_unique<ActionParser> (&action_manager, subcontexts));parser.AddSectionParser("import", std::make_unique<ImportParser> (&parser));return parser; } // \system\core\init\parser.cpp ParseData() L 42 void Parser::ParseData(const std::string& filename, const std::string& data, size_t* parse_errors) {...for (;;) {switch (next_token(&state)) {case T_EOF:end_section();return;case T_NEWLINE:...if (section_parsers_.count(args[0])) {end_section();section_parser = section_parsers_[args[0]].get();section_start_line = state.line;if (auto result =section_parser->ParseSection(std::move(args), filename, state.line);// L95!result) {(*parse_errors)++;LOG(ERROR) << filename << ": " << state.line << ": " << result.error();section_parser = nullptr;}} else if (section_parser) {if (auto result = section_parser- >ParseLineSection(std::move(args), state.line);// L102!result) {(*parse_errors)++;LOG(ERROR) << filename << ": " << state.line << ": " << result.error();}}args.clear();break;case T_TEXT:args.emplace_back(state.text);break;}} } // \system\core\init\service.cpp ParseSection() L1180 Result<Success> ServiceParser::ParseSection(std::vector<std::string>&& args,const std::string& filename, int line) {if (args.size() < 3) {return Error() << "services must have a name and a program";}const std::string& name = args[1];if (!IsValidName(name)) {return Error() << "invalid service name '" << name << "'";}Subcontext* restart_action_subcontext = nullptr;if (subcontexts_) {for (auto& subcontext : *subcontexts_) {if (StartsWith(filename, subcontext.path_prefix())) {restart_action_subcontext = &subcontext;break;}}}std::vector<std::string> str_args(args.begin() + 2, args.end());service_ = std::make_unique<Service>(name, restart_action_subcontext, str_args);//構建出一個service對象return Success(); } // \system\core\init\service.cpp ParseLineSection() L1206 Result<Success> ServiceParser::ParseLineSection(std::vector<std::string>&& args, int line) {return service_ ? service_->ParseLine(std::move(args)) : Success(); } // \system\core\init\service.cpp EndSection() L1210 Result<Success> ServiceParser::EndSection() {if (service_) {Service* old_service = service_list_->FindService(service_->name());if (old_service) {if (!service_->is_override()) {return Error() << "ignored duplicate definition of service '" << service_->name()<< "'";}service_list_->RemoveService(*old_service);old_service = nullptr;}service_list_->AddService(std::move(service_)); }return Success(); } // \system\core\init\service.cpp AddService() L1082 void ServiceList::AddService(std::unique_ptr<Service> service) {services_.emplace_back(std::move(service)); } 上面解析完成后,接下來就是啟動Service,這里我們以啟動Zygote來分析 # \system\core\rootdir\init.rc L680 on nonencryptedclass_start main //class_start是一個命令,通過do_class_start函數處理class_start late_start // \system\core\init\builtins..cpp do_class_start() L101 static Result<Success> do_class_start(const BuiltinArguments& args) {// Starting a class does not start services which are explicitly disabled.// They must be started individually.for (const auto& service : ServiceList::GetInstance()) {if (service->classnames().count(args[1])) {if (auto result = service->StartIfNotDisabled(); !result) {LOG(ERROR) << "Could not start service '" << service->name()<< "' as part of class '" << args[1] << "': " << result.error();}}}return Success(); } // \system\core\init\service.cpp StartIfNotDisabled() L977 Result<Success> Service::StartIfNotDisabled() {if (!(flags_ & SVC_DISABLED)) {return Start();} else {flags_ |= SVC_DISABLED_START;}return Success(); } // \system\core\init\service.cpp Start() L785 Result<Success> Service::Start() {//如果service已經運行,則不啟動if (flags_ & SVC_RUNNING) {if ((flags_ & SVC_ONESHOT) && disabled) {flags_ |= SVC_RESTART;}// It is not an error to try to start a service that is already running.return Success(); }...//判斷需要啟動的service的對應的執行文件是否存在,不存在則不啟動servicestruct stat sb;if (stat(args_[0].c_str(), &sb) == -1) {flags_ |= SVC_DISABLED;return ErrnoError() << "Cannot find '" << args_[0] << "'";}std::string scon;if (!seclabel_.empty()) {scon = seclabel_;} else {auto result = ComputeContextFromExecutable(args_[0]);if (!result) {return result.error();}scon = *result;}LOG(INFO) << "starting service '" << name_ << "'...";//如果子進程沒有啟動,則調用fork函數創建子進程pid_t pid = -1;if (namespace_flags_) {pid = clone(nullptr, nullptr, namespace_flags_ | SIGCHLD, nullptr);} else {pid = fork();}if (pid == 0) {//當期代碼邏輯在子進程中運行umask(077);//調用execv函數,啟動sevice子進程if (!ExpandArgsAndExecv(args_)) {PLOG(ERROR) << "cannot execve('" << args_[0] << "')";}_exit(127);}return Success(); }Zygote概敘
Zygote中文翻譯為“受精卵”,正如其名,它主要用于孵化子進程。在Android系統中有以下兩種程序:
java應用程序,主要基于ART虛擬機,所有的應用程序apk都屬于這類native程序,也就是利用C或C++語
言開發的程序,如bootanimation。所有的Java應用程序進程及系統服務SystemServer進程都由Zygote
進程通過Linux的fork()函數孵化出來的,這也就是為什么把它稱為Zygote的原因,因為他就像一個受精
卵,孵化出無數子進程,而native程序則由Init程序創建啟動。Zygote進程最初的名字不是“zygote”而是
“app_process”,這個名字是在Android.mk文件中定義的
Zgyote是Android中的第一個art虛擬機,他通過socket的方式與其他進程進行通信。這里的“其他進程”
其實主要是系統進程——SystemServer
Zygote是一個C/S模型,Zygote進程作為服務端,它主要負責創建Java虛擬機,加載系統資源,啟
動SystemServer進程,以及在后續運行過程中啟動普通的應用程序,其他進程作為客戶端向它發
出“孵化”請求,而Zygote接收到這個請求后就“孵化”出一個新的進程。比如,當點擊Launcher里的
應用程序圖標去啟動一個新的應用程序進程時,這個請求會到達框架層的核心服務
ActivityManagerService中,當AMS收到這個請求后,它通過調用Process類發出一個“孵化”子進
程的Socket請求,而Zygote監聽到這個請求后就立刻fork一個新的進程出來
Zygote觸發過程
1. init.zygoteXX.rc
import /init.${ro.zygote}.rc
${ro.zygote} 會被替換成 ro.zyogte 的屬性值,這個是由不同的硬件廠商自己定制的,
有四個值,
zygote32: zygote 進程對應的執行程序是 app_process (純 32bit 模式)
zygote64: zygote 進程對應的執行程序是 app_process64 (純 64bit 模式)
zygote32_64: 啟動兩個 zygote 進程 (名為 zygote 和 zygote_secondary),對應的執行程序分別
是 app_process32 (主模式)
zygote64_32: 啟動兩個 zygote 進程 (名為 zygote 和 zygote_secondary),對應的執行程序分別
是 app_process64 (主模式)、app_process32
2. start zygote
位置:system\core\rootdir\init.rc 560
zygote-start 是在 on late-init 中觸發的
# Mount filesystems and start core system services. on late-inittrigger early-fs# Mount fstab in init.{$device}.rc by mount_all command. Optional parameter# '--early' can be specified to skip entries with 'latemount'.# /system and /vendor must be mounted by the end of the fs stage,# while /data is optional.trigger fstrigger post-fs# Mount fstab in init.{$device}.rc by mount_all with '--late' parameter# to only mount entries with 'latemount'. This is needed if '--early' is# specified in the previous mount_all command on the fs stage.# With /system mounted and properties form /system + /factory available,# some services can be started.trigger late-fs# Now we can mount /data. File encryption requires keymaster to decrypt# /data, which in turn can only be loaded when system properties are present.trigger post-fs-data# Now we can start zygote for devices with file based encryptiontrigger zygote-start # zygote-start 是在 on late-init 中觸發的# Load persist properties and override properties (if enabled) from /data.trigger load_persist_props_action# Remove a file to wake up anything waiting for firmware.trigger firmware_mounts_completetrigger early-boottrigger boot if (bootmode == "charger") {am.QueueEventTrigger("charger");} else {am.QueueEventTrigger("late-init");}3. app_processXX
位置\frameworks\base\cmds\app_process\
Zygote啟動過程
位置\frameworks\base\cmds\app_process\app_main.cpp
在app_main.cpp的main函數中,主要做的事情就是參數解析. 這個函數有兩種啟動模式:
1. 一種是zygote模式,也就是初始化zygote進程,傳遞的參數有--start-system-server --socket-
name=zygote,前者表示啟動SystemServer,后者指定socket的名稱
2. 一種是application模式,也就是啟動普通應用程序,傳遞的參數有class名字以及class帶的參數
兩者最終都是調用AppRuntime對象的start函數,加載ZygoteInit或RuntimeInit兩個Java類,并將之前
整理的參數傳入進去
app_process
// \frameworks\base\cmds\app_process\app_main.cpp main() L280 if (strcmp(arg, "--zygote") == 0) {zygote = true;niceName = ZYGOTE_NICE_NAME;} else if (strcmp(arg, "--start-system-server") == 0) {startSystemServer = true;} else if (strcmp(arg, "--application") == 0) {application = true;} // L349 ?? if (zygote) {//這些Java的應用都是通過 AppRuntime.start(className)開始的//其實AppRuntime是AndroidRuntime的子類,它主要實現了幾個回調函數,而start()方 法是實現在AndroidRuntime這個方法類里runtime.start("com.android.internal.os.ZygoteInit", args, zygote);} else if (className) {runtime.start("com.android.internal.os.RuntimeInit", args, zygote);}app_process 里面定義了三種應用程序類型:
1. Zygote: com.android.internal.os.ZygoteInit
2. System Server, 不單獨啟動,而是由Zygote啟動
3. 其他指定類名的Java 程序
?
總結
以上是生活随笔為你收集整理的系统进程启动流程分析(一)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 如何讲解一个C语言程序,解读第一个C++
- 下一篇: 鸿蒙系统体验报告,我雷某人摊牌了,鸿蒙2