天天看點

詳解Android是如何啟動的

android系統啟動過程

首先看一張android架構結構圖

  

詳解Android是如何啟動的

linux核心啟動之後就到android init程序,進而啟動android相關的服務和應用。

啟動的過程如下圖所示:(圖檔來自網上,後面有位址)

    

詳解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圖來加深了解:

詳解Android是如何啟動的

參考文檔:

繼續閱讀