深入理解AIL語言及init.rc文件

init.rc簡介

init.rc文件由系統(tǒng)第一個啟動的init程序進行解析.它由"Android Init Language"語言編寫而成.init.rc文件可以在你android設備根目錄下找到.還記得我們上次編譯的Android源碼么?如果你已經(jīng)編譯過源碼了,那么可以在out/target/generic/root/目錄下找到該文件.

要想讀懂init.rc文件,首先要掌握Android Init Language語言,即AIL.在/system/core/init/下有一份readme.txt文件,為我們詳細介紹了有關(guān)AIL的知識.我們下面的學習同樣是借助了該文檔來的.


AIL語法

AIL語言非常簡單,主要包括兩部分:結(jié)構(gòu)語法及注釋語法.下面我們就這兩點進行說明

結(jié)構(gòu)語法

AIL語言包含主要包含五種結(jié)構(gòu)語法:

  1. Actions
  2. Services
  3. Options
  4. Commands
  5. Imports

需要注意,AIL采用是面向行的代碼風格,即用換行符作為一條語句的分隔符,也就是在init.rc中以一條語句通常占據(jù)一行.如果一行寫不下,可以在行尾添加反斜杠來鏈接到下一行,換言之,通過行尾添加反斜杠符可以將多行代碼鏈接為一行代碼.

init.rc有許多Service和Action組成.那么什么是Service和Action呢?
Action和Service顯式聲明了一個語句塊,而Commands和Options則分別用來定義Actions和Service(你可以理解為這是Action或者Service的屬性).

另外,我們聲明的Commands和Options屬于最近聲明的語句塊,即就近原則.需要注意,在第一個語句塊之前的commands和options會被忽略.

每個Actions或者Services應該有唯一的名字.對于名字重復的情況,Action和Service有自己不同的處理方式:

如果第二個定義的Action的名字和之前存在Action的名字相同,第二個Action中定義的Commands將會被添加到已經(jīng)存在的同名Action中.如果第二個定義的Service的名字和之前存在的Service的名字相同,第二個Service會被忽略并輸出錯誤信息.

注釋語法

AIL中的注釋語法和Shell腳本一致,以#開頭即可


結(jié)構(gòu)語法詳解

Actions

Actions代表一些Action.Action代表一組命令,它包含一個觸發(fā)器,該觸發(fā)器決定了何時執(zhí)行這個Action,即在什么情況下才能執(zhí)行該Action中的定義命令.當一些條件滿足觸發(fā)器的條件時,該Action中定義的命令會被添加到要執(zhí)行命令隊列的尾部(如果這組命令已經(jīng)在隊列中,則不會再次添加).

當一個Action從隊列移除時,該Action定義的命令會依次被執(zhí)行.

Action的格式如下:

on <trgger> [&& <trigger>]*
   <command>
   <command>
   <command>
   ...

不難發(fā)現(xiàn)Action都是以on開始,隨后會定義觸發(fā)器(trigger),接著便是為其定義命令(Commmand).在開始講解Trigger和Command之前,我們先來看一段Action的示例代碼:

on boot
    # 初始化網(wǎng)絡
    ifup lo
    hostname localhost
    domainname localdomain

trigger

trigger即我們上面所說的觸發(fā)器,本質(zhì)上是一個字符串,能夠匹配某種包含該字符串的事件.
trigger又被細分為事件觸發(fā)器(event trigger)和屬性觸發(fā)器(property trigger).

事件觸發(fā)器可由"trigger"命令或初始化過程中通過QueueEventTrigger()觸發(fā),通常是一些事先定義的簡單字符串,例如:boot,late-init
屬性觸發(fā)器是當指定屬性的變量值變成指定值時觸發(fā),其格式為property:<name>=*

一個Action可以有多個屬性觸發(fā)器,但是最多有一個事件觸發(fā)器.下面我們看兩個例子:

on boot && property:a=b

該Action只有在boot事件發(fā)生時,并且屬性a和b相等的情況下才會被觸發(fā).

on property:a=b && property:c=d

該Action會在以下三種情況被觸發(fā):

  • 在啟動時,如果屬性a的值等于b并且屬性c的值等于d
  • 在屬性c的值已經(jīng)是d的情況下,屬性a的值被更新為b
  • 在屬性a的值已經(jīng)是b的情況下,屬性c的值被更新為d

當前AIL中常用的有以下幾種事件觸發(fā)器:

類型 說明
boot init.rc被裝載后觸發(fā)
device-added-<path> 指定設備被添加時觸發(fā)
device-removed-<path> 指定設備被移除時觸發(fā)
service-exited-<name> 在特定服務(service)退出時觸發(fā)
early-init 初始化之前觸發(fā)
late-init 初始化之后觸發(fā)
init 初始化時觸發(fā)

Commands

Commands代表一組命令,在為Action設置了觸發(fā)器后,就需要為其定義一組命令(command)了.AIL中內(nèi)置了眾多的命令,下面我們做個簡單的說明:

命令 解釋
bootchart_init 如果配置了bootcharing,則啟動.包含在默認的init.rc中
chmod 更改文件權(quán)限
chown <owner> <group> <path> 更改文件的所有者和組
calss_start <serviceclass> 啟動指定類別服務下的所有未啟動的服務
class_stop <serviceclass> 停止指定類別服務類下的所有已運行的服務
class_reset <serviceclass> 停止指定類別的所有服務(服務還在運行),但不會禁用這些服務.后面可以通過class_start重啟這些服務
copy <src> <dst> 復制文件,對二進制/大文件非常有用
domainname <name> 設置域名稱
enable <servicename> 啟用已經(jīng)禁用的服務
exec [ <seclabel> [ <user> [ <group> ]* ]]
--<command> [ <argument> ]*
fork一個進程執(zhí)行指定命令,如果有參數(shù),則帶參數(shù)執(zhí)行
export <name> 在全局環(huán)境中,將<name>變量的值設置為<value>,即以鍵值對的方式設置全局環(huán)境變量.這些變量對之后的任何進程都有效
hostname 設置主機名
ifup <interface> 啟動某個網(wǎng)絡接口
insmod [-f] <path> [<options>] 加載指定路徑下的驅(qū)動模塊。-f強制加載檬果,即不管當前模塊是否和linux kernel匹配
load_all_props 從/system抄邀,/vendor加載屬性饵史。默認包含在init.rc
load_persist_props 當/data被加密時,加載固定屬性
loglevel <level> 設置kernel日志等級
mkdir <path> [mode] [owner] [group] 在制定路徑下創(chuàng)建目錄
mount_all <fstab> [ <path> ]* 在給定的fs_mgr-format上調(diào)用fs_mgr_mount和引入rc文件
mount <type> <device> <dir>[ <flag> ]* [<options>] 掛載指定設備到指定目錄下.
powerct 用來應對sys.powerctl中系統(tǒng)屬性的變化,用于系統(tǒng)重啟
restart <service> 重啟制定服務非洲,但不會禁用該服務
restorecon <path> [ <path> ]* 恢復指定文件到file_contexts配置中指定的安全上線文環(huán)境
restorecon_recursive <path> [ <path> ]* 以遞歸的方式恢復指定目錄到file_contexts配置中指定的安全上下文中
rm <path> 刪除指定路徑下的文件
rmdir <path> 刪除制定路徑下的目錄
setprop <name> <value> 將系統(tǒng)屬性<name>的值設置為<value>,即以鍵值對的方式設置系統(tǒng)屬性
setrlimit <resource> <cur> <max> 設置資源限制
start <service> 啟動服務(如果該服務還未啟動)
stop <service> 關(guān)閉服務(如果該服務還未停止)
swapon_all <fstab>
symlink <target> <path> 創(chuàng)建一個指向<path>的符合鏈接<target>
sysclktz <mins_west_of_gmt> 設置系統(tǒng)時鐘的基準,比如0代表GMT,即以格林尼治時間為準
trigger <event> 觸發(fā)一個事件,將該action排在某個action之后(用于Action排隊)
verity_load_state
verity_update_state <mount_point>
wait <path> [ <timeout> ] 等待一個文件是否存在,存在時立刻返回或者超時后返回.默認超時事件是5s
write <path> <content> 寫內(nèi)容到指定文件中

Services

Services代表一些Service.Service是一些在系統(tǒng)初始化時就啟動或者退出時需要重啟的程序.其格式如下:

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

不難發(fā)現(xiàn),首先需要為服務定義名字,并指定程序路徑,然后便是通過option來修飾服務.同樣先來看一下示例:

service ueventd /sbin/ueventd
    class core
    critical
    seclabel u:r:ueventd:s0

Options

Options代表一些option.option用來修飾服務,決定了服務在什么時候運行以及怎樣運行.AIL中提供了非常多的option,下面我們做個簡單說明:

選項 解釋
console 服務需要一個控制臺.
critical 表示這是一個關(guān)鍵設備服務.如果4分鐘內(nèi)此服務退出4次以上,那么這個設備將重啟進入recovery模式
disabled 服務不會自動啟動,必須通過服務名顯式啟動
setenv <name> <value> 在進程啟動過程中,將環(huán)境變量<name>的值設置為<value>,即以鍵值對的方式設置環(huán)境變量
socket <name> <type> <perm> [ <user> [ <group> [seclabel]]] 創(chuàng)建一個unix域下的socket,其被命名/dev/socket/<name>. 并將其文件描述符fd返回給服務進程.其中,type必須為dgram,stream或者seqpacke,user和group默認是0.seclabel是該socket的SELLinux的安全上下文環(huán)境,默認是當前service的上下文環(huán)境,通過seclabel指定.
user <username> 在執(zhí)行此服務之前切換用戶名,當前默認的是root.自Android M開始,即使它要求linux capabilities,也應該使用該選項.很明顯,為了獲得該功能,進程需要以root用戶運行
group <groupname> 在執(zhí)行此服務之前切換組名,除了第一個必須的組名外,附加的組名用于設置進程的補充組(借助setgroup()函數(shù)),當前默認的是root
seclabel <seclabel> 在執(zhí)行該服務之前修改其安全上下文,默認是init程序的上下文
oneshot 當服務退出時,不重啟該服務
class <name> 為當前service設定一個類別.相同類別的服務將會同時啟動或者停止,默認類名是default.
onrestart 當服務重啟時執(zhí)行該命令
priority <priority> 設置服務進程的優(yōu)先級.優(yōu)先級取值范圍為-20~19,默認是0.可以通過setpriority()設置

Imports

用來引入一個要解析的其他配置文件,通常用于當前配置文件的擴展.
其格式如下:

import <path>

如果path是個一個目錄,則該目錄下的每個.rc文件都被引入.

在初始化過程中,共有兩次使用import來引入.rc文件:

  1. 在初始化引導期間,引入/init.rc文件
  2. 在執(zhí)行mount_all命令時,引入/{system,vendor,odm}/etc/init/或者指定路徑下的.rc文件

我們來看看init.rc文件引入的.rc文件:

import /init.environ.rc
import /init.usb.rc
import /init.${ro.hardware}.rc
import /init.${ro.zygote}.rc

Properties

Properties代表Init進程運行中的一些屬性信息.在Init運行中,通過以下屬性能夠獲取當前程序內(nèi)部信息:

類型 說明
init.svc.<name> 指定名稱服務的狀態(tài),有stopped,stopping,runing,restarting這種四種狀態(tài)
init.action 獲取當前正在執(zhí)行的action
init.command 獲取當前正在執(zhí)行的command

文件示例

到現(xiàn)在為止,有關(guān)AIL相關(guān)的知識基本介紹完畢,下面截取init.rc文件中的一段來做個簡單的說明:

//引入其他要解析的rc文件
import /init.environ.rc
import /init.usb.rc
import /init.${ro.hardware}.rc
import /init.usb.configfs.rc
import /init.${ro.zygote}.rc

#定義了一個action,在init初始化之前觸發(fā)
on early-init
    # Set init and its forked children's oom_adj.
    write /proc/1/oom_score_adj -1000

    # Disable sysrq from keyboard
    write /proc/sys/kernel/sysrq 0

    # Set the security context of /adb_keys if present.
    restorecon /adb_keys

    # Shouldn't be necessary, but sdcard won't start without it. http://b/22568628.
    mkdir /mnt 0775 root system

    # Set the security context of /postinstall if present.
    restorecon /postinstall
    
    #啟動ueventd服務
    start ueventd
    
    #...省略多行...
    
#定義ueventd服務,設置服務為/sbin/ueventd
service ueventd /sbin/ueventd
    class core#為其設置類名為core
    critical#表明這是一個關(guān)鍵服務
    seclabel u:r:ueventd:s0 #設置其安全上下文

總結(jié)

AIL是一種非常簡單的語言,主要用于定義啟動流程中需要做的事情.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末操灿,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子溉卓,更是在濱河造成了極大的恐慌,老刑警劉巖搬泥,帶你破解...
    沈念sama閱讀 216,402評論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件桑寨,死亡現(xiàn)場離奇詭異,居然都是意外死亡忿檩,警方通過查閱死者的電腦和手機尉尾,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來燥透,“玉大人沙咏,你說我怎么就攤上這事“嗵祝” “怎么了肢藐?”我有些...
    開封第一講書人閱讀 162,483評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長吱韭。 經(jīng)常有香客問我吆豹,道長,這世上最難降的妖魔是什么理盆? 我笑而不...
    開封第一講書人閱讀 58,165評論 1 292
  • 正文 為了忘掉前任痘煤,我火速辦了婚禮,結(jié)果婚禮上猿规,老公的妹妹穿的比我還像新娘衷快。我一直安慰自己,他們只是感情好坎拐,可當我...
    茶點故事閱讀 67,176評論 6 388
  • 文/花漫 我一把揭開白布烦磁。 她就那樣靜靜地躺著养匈,像睡著了一般哼勇。 火紅的嫁衣襯著肌膚如雪都伪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,146評論 1 297
  • 那天积担,我揣著相機與錄音陨晶,去河邊找鬼。 笑死帝璧,一個胖子當著我的面吹牛先誉,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播的烁,決...
    沈念sama閱讀 40,032評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼褐耳,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了渴庆?” 一聲冷哼從身側(cè)響起铃芦,我...
    開封第一講書人閱讀 38,896評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎襟雷,沒想到半個月后刃滓,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,311評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡耸弄,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,536評論 2 332
  • 正文 我和宋清朗相戀三年咧虎,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片计呈。...
    茶點故事閱讀 39,696評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡砰诵,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出捌显,到底是詐尸還是另有隱情胧砰,我是刑警寧澤,帶...
    沈念sama閱讀 35,413評論 5 343
  • 正文 年R本政府宣布苇瓣,位于F島的核電站尉间,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏击罪。R本人自食惡果不足惜哲嘲,卻給世界環(huán)境...
    茶點故事閱讀 41,008評論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望媳禁。 院中可真熱鬧眠副,春花似錦、人聲如沸竣稽。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至娃弓,卻和暖如春典格,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背台丛。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評論 1 269
  • 我被黑心中介騙來泰國打工耍缴, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人挽霉。 一個月前我還...
    沈念sama閱讀 47,698評論 2 368
  • 正文 我出身青樓防嗡,卻偏偏與公主長得像,于是被迫代替她去往敵國和親侠坎。 傳聞我的和親對象是個殘疾皇子蚁趁,可洞房花燭夜當晚...
    茶點故事閱讀 44,592評論 2 353

推薦閱讀更多精彩內(nèi)容