51CTO專家專欄 李洋談Android系統(tǒng)啟動過程剖析
原創(chuàng)【51CTO獨家特稿】李洋老師在前文中向我們介紹了“Android安全框架”和“Android系統(tǒng)及程序授權機制”。李洋老師將繼續(xù)介紹Android系統(tǒng)架構(gòu)的介紹——《Android系統(tǒng)啟動過程剖析》。
1. 系統(tǒng)啟動流程簡介
在Linux內(nèi)核啟動后,init 1(1號進程)將作為第一個用戶空間(Linux虛擬內(nèi)存的大小為232(在32位的x86機器上),內(nèi)核將這4G字節(jié)的空間分為兩部分。最高的1G字節(jié)供內(nèi)核使用,稱為“內(nèi)核空間”。而較低的3G字節(jié)供各個進程使用,稱為“用戶空間”。)的進程來啟動Android系統(tǒng),該啟動流程可以分為如下5個階段,如下圖:
(1) 啟動準備:該階段包括創(chuàng)建文件系統(tǒng)的基本目錄、打開基本輸入、輸出設備,初始化日志功能等;
(2) 解析init.rc文件:該階段對init.rc腳本文件進行解析,主要對Service(服務)和Action(動作)進行解析。其中,Service由命令(Command)和一系列服務的附加內(nèi)容(Option,選項)組成,如:“service vold /system/bin/vold”為一個Service,而“socket vold stream 0660 root mount“則為配合該服務使用的Option;Action則由一系列的命令組成,如:“on init mkdir /system”為系統(tǒng)初始化時建立系統(tǒng)文件夾的Action;
(3) 觸發(fā)需要執(zhí)行的action:Action需要在Triggers(觸發(fā)條件)中調(diào)用,本階段對需要執(zhí)行的Action進行觸發(fā),并根據(jù)觸發(fā)條件將需要執(zhí)行的Action放入Action隊列;
(4) 執(zhí)行在action隊列中的命令:對上一階段觸發(fā)的Action以及Service進行執(zhí)行。并在此過程中,派生了Zygote和Service Manager兩個非常重要的進程;
(5) 循環(huán)處理事件:init進程進入無限循環(huán),處理設備插入/拔出,服務屬性狀態(tài)變化和signal事件等。
2. 源碼分析結(jié)果
對android-2.3.3_r1版本中的如下源碼文件進行分析:
(1) init.c:路徑為system/core/init/init.c
(2) init_parser.c:路徑為system/core/init/ init_parser.c
(3) builtins.c:路徑為system/core/init/ builtins.c
(4) property_service.c:路徑為system/core/init/property_service.c
(5) keycords.c:路徑為system/core/init/keycords.c
(6) signal_handler.c:路徑為system/core/init/signal_handler.c
總結(jié)得出系統(tǒng)啟動流程對應的源代碼文件及函數(shù)如下(注:以下函數(shù)間的順序執(zhí)行關系使用“>”表示;函數(shù)間的調(diào)用執(zhí)行關系使用“à”表示)
2.1 第一階段(啟動準備)
具體的函數(shù)執(zhí)行過程如下:
mkdir > mount > open_devnull_stdio > log_init |
2.2 第二階段(解析init.rc文件)
具體的函數(shù)調(diào)用過程如下:
init_parse_config_fileàparse_configà parse_new_sectionàparse_service (或者parse_action)-> parse_line_service(或者parce_line_action) |
2.3 第三階段(觸發(fā)需要執(zhí)行的action)
具體的調(diào)用過程如下:
action_for_each_trigger("boot", action_add_queue_tail);à action_add_queue_tail ( class_start default) à action_remove_queue_head à do_class_start |
2.4 第四階段(執(zhí)行在action隊列中的命令)
具體的調(diào)用過程如下:
execute_one_commandà action_remove_queue_head àdo_class_start àservice_for_each_classà service_start_if_not_disabledà service_start |
2.5 第五階段(循環(huán)處理)
具體的循環(huán)處理過程如下:
- for (; ;) {
- poll > handle_property_set_fd > handle_keychord > handle_signal
- }
2.6 主要函數(shù)介紹
函數(shù)名 | 所在文件 | 功能概述 |
main | system/core/init/init.c | 1號進程init的入口函數(shù)。主要分析init.rc配置文件,執(zhí)行基本的action和啟動必備的native service,然后進入一個infinite loop 處理來自property, signal的event |
mkdir | system/core/init/init.c | 建立文件系統(tǒng)的基本目錄 |
mount | system/core/init/init.c | 裝載文件系統(tǒng) |
open_devnull_stdio | system/core/init/init.c | 打開基本輸入、輸出設備 |
log_init | system/core/init/init.c | 初始化日志功能 |
init_parse_config_file | system/core/init/ init_parser.c | 讀取init.rc文件內(nèi)容到內(nèi)存數(shù)據(jù)區(qū) |
parse_config | system/core/init/ init_parser.c | 識別init.rc文件中的 Section(service and action series )和Text |
parse_new_section | system/core/init/ init_parser.c | 識別section類別 |
parse_service | system/core/init/ init_parser.c | 對service section第一行進行分析 |
parse_line_service | system/core/init/ init_parser.c | 對service section的option選項進行分析 |
parse_action | system/core/init/ init_parser.c | 對action section第一行進行分析 |
parse_line_action | system/core/init/ init_parser.c | 對action section的每一行獨立的命令進行分析 |
action_for_each_trigger | system/core/init/ init_parser.c | 觸發(fā)某個action的執(zhí)行 |
action_add_queue_tail | system/core/init/ init_parser.c | 將某個action的從action_list加到action_queue |
execute_one_command | system/core/init/init.c | 執(zhí)行當前action的一個command |
action_remove_queue_head | system/core/init/ init_parser.c | 從action_queue鏈表上移除頭結(jié)點(action) |
do_class_start | system/core/init/ builtins.c | class_start default對應的入口函數(shù),主要用于啟動native service |
service_for_each_class | system/core/init/ init_parser.c | 遍歷service_list鏈表上的所有結(jié)點 |
service_start_if_not_disabled | system/core/init/ builtins.c | 判斷service的flag是否disabled,如果不是,則調(diào)用相關函數(shù),準備啟動service |
service_start | system/core/init/init.c | 啟動service的主要入口函數(shù),設置service數(shù)據(jù)結(jié)構(gòu)的相關數(shù)據(jù)結(jié)構(gòu)后,調(diào)用fork創(chuàng)建一個新的進行,然后調(diào)用execve執(zhí)行新的service |
fork | Lib function(ulibc) | 進程創(chuàng)建函數(shù) |
execve | Lib function(ulibc) | 調(diào)用執(zhí)行新的service |
poll | Lib function(ulibc) | 查詢property_set_fd,signal_fd和keychord_fd文件句柄是否有服務請求 |
handle_property_set_fd | system/core/init/property_service.c | 處理系統(tǒng)屬性服務請求,如:service, wlan和dhcp等等 |
handle_keychord | system/core/init/keycords.c | 處理注冊在service structure上的keychord,通常是啟動service |
handle_signal | system/core/init/signal_handler.c | 處理SIGCHLD signal |
【編輯推薦】