Android系統啟動過程剖析

lostinai發表於2014-01-02

1. 系統啟動流程簡介

在Linux核心啟動後,init 1(1號程式)將作為第一個使用者空間(Linux虛擬記憶體的大小為232(在32位的x86機器上),核心將這4G位元組的空間分為兩部分。最高的1G位元組供核心使用,稱為“核心空間”。而較低的3G位元組供各個程式使用,稱為“使用者空間”。)的程式來啟動Android系統,該啟動流程可以分為如下5個階段,如下圖:




(1) 啟動準備:該階段包括建立檔案系統的基本目錄、開啟基本輸入、輸出裝置,初始化日誌功能等;

(2) 解析init.rc檔案:該階段對init.rc指令碼檔案進行解析,主要對Service(服務)和Action(動作)進行解析。其中,Service由命令(Command)和一系列服務的附加內容(Option,選項)組成,如:“service vold /system/bin/vold”為一個Service,而“socket vold stream 0660 root mount“則為配合該服務使用的Option;Action則由一系列的命令組成,如:“on init mkdir /system”為系統初始化時建立系統資料夾的Action;

(3) 觸發需要執行的action:Action需要在Triggers(觸發條件)中呼叫,本階段對需要執行的Action進行觸發,並根據觸發條件將需要執行的Action放入Action佇列;

(4) 執行在action佇列中的命令:對上一階段觸發的Action以及Service進行執行。並在此過程中,派生了Zygote和Service Manager兩個非常重要的程式;

(5) 迴圈處理事件:init程式進入無限迴圈,處理裝置插入/拔出,服務屬性狀態變化和signal事件等。

2. 原始碼分析結果

對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

總結得出系統啟動流程對應的原始碼檔案及函式如下(注:以下函式間的順序執行關係使用“>”表示;函式間的呼叫執行關係使用“à”表示)

2.1 第一階段(啟動準備)

具體的函式執行過程如下:

 mkdir > mount > open_devnull_stdio > log_init

2.2 第二階段(解析init.rc檔案)

具體的函式呼叫過程如下:

 init_parse_config_fileàparse_configà parse_new_sectionàparse_service (或者parse_action)-> parse_line_service(或者parce_line_action)

2.3 第三階段(觸發需要執行的action)

具體的呼叫過程如下:

 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 第四階段(執行在action佇列中的命令)

具體的呼叫過程如下:

 execute_one_commandà action_remove_queue_head àdo_class_start àservice_for_each_classà service_start_if_not_disabledà service_start

2.5 第五階段(迴圈處理)

具體的迴圈處理過程如下:

  1. for (; ;) { 
  2. poll > handle_property_set_fd > handle_keychord > handle_signal 

2.6 主要函式介紹

函式名 所在檔案 功能概述
main system/core/init/init.c 1號程式init的入口函式。主要分析init.rc配置檔案,執行基本的action和啟動必備的native service,然後進入一個infinite loop 處理來自property, signal的event 
mkdir system/core/init/init.c 建立檔案系統的基本目錄
mount system/core/init/init.c 裝載檔案系統
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檔案內容到記憶體資料區
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 觸發某個action的執行 
action_add_queue_tail system/core/init/ init_parser.c 將某個action的從action_list加到action_queue
execute_one_command system/core/init/init.c 執行當前action的一個command
action_remove_queue_head system/core/init/ init_parser.c 從action_queue連結串列上移除頭結點(action)
do_class_start system/core/init/ builtins.c class_start default對應的入口函式,主要用於啟動native service
service_for_each_class system/core/init/ init_parser.c 遍歷service_list連結串列上的所有結點
service_start_if_not_disabled system/core/init/ builtins.c 判斷service的flag是否disabled,如果不是,則呼叫相關函式,準備啟動service
service_start system/core/init/init.c 啟動service的主要入口函式,設定service資料結構的相關資料結構後,呼叫fork建立一個新的進行,然後呼叫execve執行新的service
fork Lib function(ulibc) 程式建立函式
execve Lib function(ulibc) 呼叫執行新的service
poll Lib function(ulibc) 查詢property_set_fd,signal_fd和keychord_fd檔案控制程式碼是否有服務請求
handle_property_set_fd system/core/init/property_service.c 處理系統屬性服務請求,如:service, wlan和dhcp等等
handle_keychord system/core/init/keycords.c 處理註冊在service structure上的keychord,通常是啟動service
handle_signal system/core/init/signal_handler.c 處理SIGCHLD signal

相關文章