1. 程式人生 > >android init進程分析 init腳本解析和處理

android init進程分析 init腳本解析和處理

還要 ret process ram ces ken option restart launch

(懶人近期想起我還有csdn好久沒打理了。這個android init躺在我的草稿箱中快5年了。略微改改發出來吧)

RC文件格式

rc文件是linux中常見的啟動載入階段運行的文件。rc是run commands的縮寫。基本上能夠理解為在啟動階段運行的一些列命令。android init進程啟動時,也會運行此啟動腳本文件,init.rc。init.rc的寫法稍有點復雜,具體可參考 /system/core/init下的readme文件。腳本基本組成是由四類,為:

  • commands: 命令
  • action: 動作
  • services: 服務
  • options: 選項

該語言的語法包含下列約定:

  • 全部類型的語句都是基於行(line-oriented)的,一個語句包括若幹個tokens,token之間通過空格字符分隔。

    假設一個token中須要包括空格字符,則須要通過C語言風格的反斜線(‘\‘)來轉義。或者使用雙引號把整個token引起來。

    反斜線還能夠出如今一行的末尾。表示下一行的內容仍然屬於當前語句。

  • 以‘#‘開始的行是凝視行(凝視僅僅能是行的第一個非空字符,這個千萬要註意)。

  • 動作(Actions)和服務(Services)語句隱含表示一個新的段落(section)的開始。

    全部的指令(commands)和選項(options)歸屬於上方近期的一個段落。在第一個段落之前的指令(commands)和選項(options)是無效的。

  • 動作(Actions)和服務(Services)擁有唯一性的名字。假設出現重名。那麽後出現的定義將被作為錯誤忽略掉【眼下還是忽略,不是覆蓋!

    】。

事實上。嚴格來說,應該就僅僅有兩種類別Action和Service:

  • Action是由特定trigger下的一堆command組成
  • Service是由一堆options描寫敘述的daemon服務組成

動作(Action)

動作(Action)是一個有名字的指令(commands)序列。每一個動作(Action)都定義一個觸發條件(trigger)。用於指示什麽時候運行這個動作。

在實際處理中。當與動作的觸發器匹配的事件發生時。該動作下的命令,將被加入到一個即將被運行的隊列的隊尾(除非它已經在隊列中)。
隊列中的每個命令被依次取出運行。

一個動作定義的形式例如以下:

on <trigger>
  <command>
  <command>
  <command>

服務(Services)

服務是初始化程序須要啟動的一些程序,初始化程序還有可能會在這些程序退出之後重新啟動它們。Services take一個服務定義的形式例如以下:

service <name> <pathname> [ <argument> ]*
  <option>
  <option>
  ...

選項(Options)

選項將影響控制初始化程序執行服務的時機和方法。可能的選項例如以下表(註意,options僅僅是作為服務的附屬部分的)..

說明:

disabled
服務在啟動所屬的class的時候,不會自己主動隨之啟動,僅僅有明白指明要啟動此服務時才會啟動(通常每一個服務都會屬於一個class中,由classkeyword描寫敘述)

socket <name> <type> <perm> [ <user> [ <group> ] ]
Create a unix domain socket named/dev/socket/<name> and pass its fd to the launched process. Valid<type> values includedgram andstream.user andgroup default to 0.

user <username>
在exec啟動此服務之前,改變進程的user。默認user是root

group <groupname> [ <groupname> ]*
周期exec啟動服務之前。改變此服務進程的group. 默認group是root。將服務增加特定的group,能夠獲取一些特定的權限。

capability [ <capability> ]+
Set linux capability before exec‘ing this service

oneshot
服務僅僅運行一次。對於非daemon程序。必需要使用onshot模式。

class <name>
設定服務的class名字,全部的服務都必須設置一個,假設不設置。默認是屬於default class的。同一個class中的服務。能夠通過命令class_start統一啟動。


觸發器(Triggers

觸發器是一個字符串,用於匹配特定的事件。這些事件將觸發觸發器所屬動作(Action)的運行。


指令(Commands

支持哪些指令。各個android版本號不盡同樣。詳情可參考/system/core/init下的readme或最好看代碼


屬性(Properties

初始化程序(Init)能夠依據須要改動一些系統的屬性。readme中說的三個:
init.action
Equal to the name of the action currently being executed or "" if none.

init.command
Equal to the command being executed or "" if none.

init.svc.<name>
State of a named service ("stopped", "running", or "restarting").

實際init進程僅僅看到更新 init.svc.<name>, 每一個服務都會創建一個這種property。能夠通過 getprop | grep init.svc 看到每一個服務的狀態,狀態切換的時候,會同一時候更新。

void notify_service_state(const char *name, const char *state)
{
    char pname[PROP_NAME_MAX];
    int len = strlen(name);
    if ((len + 10) > PROP_NAME_MAX)
        return;
    snprintf(pname, sizeof(pname), "init.svc.%s", name);
    property_set(pname, state);
}

其它兩個沒意義,實際也沒用,可能當初設計有吧,但最後也沒用(comman/action都是開機時運行,且持續時間都非常短,沒太大用處)。

init 的parser

Init的parser是比較簡單的自己主動機,代碼也不算復雜,主要parser的是三部分:

  1. service: 每一個service的描寫敘述及屬性,parser好了,放在service_list中,以便以後通過actions的命令啟動。

  2. actions: parser每一個動作, on XXX及後繼的command。就是一個action。這個parser好後。也是放在action_list中,以便在init中啟動。
  3. import: init.rc 能夠支持像c中的include一樣,包括其它init.rc。這個支持比較簡單,並非相當於在import位置插入被import的代碼。而是在主init.rc都parser好後。再依次parser被包括的rc文件。



init.rc腳本命令的運行

腳本解析好後,會將各個Actions依照時間順序,分別推到action_queue中,再一個一個運行。


actions依照trigger的時間順序,依次運行的是。默認trigger的順序例如以下:

 action_for_each_trigger("early-init", action_add_queue_tail);
 action_for_each_trigger("init", action_add_queue_tail);
 action_for_each_trigger("early-fs", action_add_queue_tail);
 action_for_each_trigger("fs", action_add_queue_tail);
 action_for_each_trigger("post-fs", action_add_queue_tail);
 action_for_each_trigger("post-fs-data", action_add_queue_tail); 
 action_for_each_trigger("early-boot", action_add_queue_tail);
 action_for_each_trigger("boot", action_add_queue_tail); 

因此。各個命令須要特別註意處理好依賴。比方在init階段。是不可能訪問data分區的。另外還要註意一下。 同一個階段中,import的rc文件,是在後面一些運行的(依據import文件的parser順序)。



service的啟動時間。須要註意一下,也是通過action中的command運行的。 比方在on boot階段:

 on boot
  ...
  class_start core


這樣。在boot階段運行到這個命令時。全部屬於core這一類的服務,都會被逐個啟動。



  

android init進程分析 init腳本解析和處理