android系統啟動過程
首先看一張android架構結構圖
linux核心啟動之後就到android init程序,進而啟動android相關的服務和應用。
啟動的過程如下圖所示:(圖檔來自網上,後面有位址)
一 init程序的啟動
init程序,它是一個由核心啟動的使用者級程序。核心自行啟動(已經被載入記憶體,開始運作,
并已初始化所有的裝置驅動程式和資料結構等)之後,就通過啟動一個使用者級程式init的方式,完成引導程序。init始終是第一個程序。
啟動過程就是代碼init.c中main函數執行過程:system\core\init\init.c
在函數中執行了:檔案夾建立,挂載,rc檔案解析,屬性設定,啟動服務,執行動作,socket監聽……
下面看兩個重要的過程:rc檔案解析和服務啟動。
1 rc檔案解析
.rc檔案是android使用的初始化腳本檔案 (system/core/init/readme.txt中有描述:
four broad classes of statements which are actions, commands, services,
and options.)
其中command 就是系統支援的一系列指令,如:export,hostname,mkdir,mount,等等,其中一部分是 linux 指令,
還有一些是 android 添加的,如:class_start <serviceclass>: 啟動服務,class_stop <serviceclass>:關閉服務,等等。
其中options是針對 service 的選項的。
系統初始化要觸發的動作和要啟動的服務及其各自屬性都在rc腳本檔案中定義。 具體看一下啟動腳本:\system\core\rootdir\init.rc
在解析rc腳本檔案時,将相應的類型放入各自的list中:
\system\core\init\init_parser.c :init_parse_config_file( )存入到
action_queue、 action_list、 service_list中,解析過程可以看一下parse_config函數,類似狀态機形式挺有意思。
這其中包含了服務:adbd、servicemanager、vold、ril-daemon、debuggerd、surfaceflinger、zygote、media……
2 服務啟動
檔案解析完成之後将service放入到service_list中。
檔案解析完成之後将service放入到service_list中。
\system\core\init\builtins.c
service的啟動是在do_class_start函數中完成:
周遊所有名稱為classname,狀态不為svc_disabled的service啟動。
do_class_start對應的指令:
keyword(class_start, command, 1, do_class_start)
init.rc檔案中搜尋class_start:class_start main 、class_start core、……
main、core即為do_class_start參數classname
init.rc檔案中service class名稱都是main:
service drm /system/bin/drmserver
class main
service surfaceflinger /system/bin/surfaceflinger
class main
于是就能夠通過main名稱周遊到所有的service,将其啟動。
do_class_start調用:
init.rc中
on boot //action
class_start core //執行command 對應 do_class_start
class_start main
init程序main函數中:
system/core/init/init.c中:
循環調用service_start,将狀态svc_restarting啟動, 将啟動後的service狀态設定為svc_running。
pid=fork();
execve();
在消息循環中:init程序執行了android的command,啟動了android的nativeservice,監聽service的變化需求,signal處理。
init程序是作為屬性服務(property service),維護這些nativeservice。
二 servicemanager啟動
在.rc腳本檔案中zygote的描述:
servicemanager用來管理系統中所有的binder service,不管是本地的c++實作的還是java語言實作的都需要
這個程序來統一管理,最主要的管理就是,注冊添加服務,擷取服務。所有的service使用前都必須先在servicemanager中進行注冊。
do_find_service( )
do_add_service( )
svcmgr_handler( )
代碼位置:frameworks\base\cmds\servicemanager\service_manager.c
三 zygote程序的啟動
zygote這個程序是非常重要的一個程序,zygote程序的建立是真正的android運作空間,初始化建立的service都是navtive service.
(1) 在.rc腳本檔案中zygote的描述:
代碼位置:frameworks/base/cmds/app_process/app_main.cpp
上面的參數在這裡就會用上,決定是否要啟動和啟動那些程序。
(2) 接着到了androidruntime類中:
frameworks\base\core\jni\androidruntime.cpp
到了zygoteinit.java中的靜态main函數中,從c++ ——》java
(3)zygoteinit
真正zygote程序:
frameworks\base\core\java\com\android\internal\os\zygoteinit.java
四 systemserver啟動
(1)在zygote程序進入循環之前,調用了startsystemserver( );
(2)runtimeinit中:
frameworks\base\core\java\com\android\internal\os\runtimeinit.java
(3)從startsystemserver開始執行并沒有去調用systemserver的任何方法,
隻是通過反射擷取了main方法,付給了methodandargscaller,并抛出了methodandargscaller異常。
此異常是在哪裡處理的呢?
回到startsystemserver( )函數的調用處:
在zygoteinit的main函數中:
如果startsystemserver抛出了異常,跳過執行zygoteinit程序的循環,這是怎麼回事呢?
在startsystemserver中異常是由handlesystemserverprocess抛出,而
pid = zygote.forksystemserver( )
/* for child process 僅對新的子程序設定 */
if (pid == 0) {
handlesystemserverprocess(parsedargs);
}
// zygote.forksystemserver根據參數fork 出一個子程序,若成功調用,則傳回兩次:
一次傳回的是 zygote 程序的 pid ,值大于0;一次傳回的是子程序 pid,值等于0否則,出錯傳回-1;
caller.run();
methodandargscaller run函數:調用前面所提到的
//systemserver main方法
m = cl.getmethod("main", new class[] { string[].class });
啟動了程序systemserver。
(4)systemserver的執行 init1( )
//frameworks\base\services\java\com\android\server\systemserver.java
processstate:
每個程序在使用binder 機制通信時,均需要維護一個processstate 執行個體來描述目前程序在binder 通信時的binder 狀态。
processstate 有如下2 個主要功能:
1. 建立一個thread, 該線程負責與核心中的binder 子產品進行通信,稱該線程為pool thread ;
2. 為指定的handle 建立一個bpbinder 對象,并管理該程序中所有的bpbinder 對象。
pool thread:
在binder ipc 中,所有程序均會啟動一個thread 來負責與bd 來直接通信,也就是不停的讀寫bd ,
這個線程的實作主體是一個ipcthreadstate 對象,下面會介紹這個類型。
下面是pool thread 的啟動方式:
processstate::self()->startthreadpool();
ipcthreadstate :
ipcthreadstate 也是以單例模式設計的。由于每個程序隻維護了一個processstate 執行個體,同時processstate 隻啟動一個pool thread ,
也就是說每一個程序隻會啟動一個pool thread ,是以每個程序則隻需要一個ipcthreadstate 即可。
pool thread 的實際内容則為:
ipcthreadstate::self()->jointhreadpool();
(5)systemserver的執行 init2( )
到這裡系統applicationframework層的xxxservicemanager準備就緒,可以開始跑上層應用了,我們的第一個上層應用homelauncher。
homeactivity又是如何啟動的呢?
activity的啟動必然和activitymanagerservice有關,我們需要去看看
activitymanagerservice.systemready( )中都幹了些什麼。
大家可以參考下面的uml圖來加深了解:
參考文檔: