Android Init Language 包含五种语句,分别是 Actions、Commands、Services、Options 以及 Imports.
- Actions 和 Services 隐式地声明了一个新的 section,所有的 Commands 和 Options 都属于最近声明的 section,在第一个 section 之前的 Commands 和 Options 会被忽略
- Actions 和 Services 都有自己的名字,如果一个 Action 定义的名字已经存在,那么属于它的 Commands 会被加到之前定义的 Action 的 Commands 的后面。如果一个 Service 定义的名字已经存在,那么它会被忽略并且一条错误信息会被记录下来
Init language 主要用在以 .rc 为后缀的纯文本文件中,在系统的多个位置都有用到它们:
- /init.rc 是主要的 .rc 文件,它是 init.cpp 在其运行的开始加载的,负责系统的初始化。它会引入 (imports) /init.${ro.hardware}.rc 文件
- 通过 mount_all 命令,init.cpp 加载在 /{system,vendor,odm}/etc/init/ 目录下的所有文件。这些目录是为在文件系统挂载之后使用的所有 Actions 和 Services 设计的
- 可以在 mount_all 命令中指定路径以使系统 import 特定路径下的 .rc 文件而不是默认的 .rc 文件,这是为了支持工厂模式和其他非一般 boot 模式。正常 boot 过程中应该使用下面这三个默认路径:
- /system/etc/init/ 中是一些核心系统项,例如 SurfaceFlinger、MediaService、logcatd 等
- /vendor/etc/init/ 中是 SoC vendor 项,例如核心 SoC 功能需要的 actions 和 daemons
- /odm/etc/init/ 中是设备定制项,例如运动传感器或者其他外设功能所需要的 actions 和 daemons
一、Actions
Actions 是 commands 的命名序列,Actions 有一个 trigger,它用来决定这个 action 应该什么时候发生。当满足 action 的 trigger 的事件发生时,这个 action 会被加到执行队列的尾部,除非队列中已经有这个 action.
队列中的每个 action 会被按次序执行并且 action 中的 command 也会被按次序执行,Actions 的格式如下所示:
on <trigger> [&& <trigger>]*
<command>
<command>
<command>
例如:
# Used to disable USB when switching states
on property:sys.usb.config=none && property:sys.usb.configfs=0
stop adbd
write /sys/class/android_usb/android0/enable 0
write /sys/class/android_usb/android0/bDeviceClass 0
setprop sys.usb.state ${sys.usb.config}
二、Services
Services 是一些程序,init 会建立它们,或者当它们退出时选择性地重启它们。Services 的格式如下所示:
service <name> <pathname> [ <argument> ]*
<option>
<option>
...
例如:
service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server
class main
socket zygote stream 660 root system
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart audioserver
onrestart restart cameraserver
onrestart restart media
onrestart restart netd
writepid /dev/cpuset/foreground/tasks
三、Options
Options 是对 Services 的修饰,他们会影响 init 什么时候以及如何运行这些 services.
critical
:如果一个 critical 的 service 在四分钟内退出超过四次,设备会重启进入 recovery 模式disabled
:这些 services 不会自动启动,它必须被通过名字显示地启动setenv <name> <value>
:在创建过程中对环境变量 name 设置 valueclass <name>
:为这个 service 指定一个 class name。所有相同 class name 的 services 会被一起启动或停止。如果没有指定,那么这个 service 的 class name 将默认为 “default”onrestart
:当 service 重启时,执行一个 commandwritepid <file...>
:当这个 service fork 时,将其孩子的 pid 写入文件当中oneshot
:当 service 退出时,不要重启socket <name> <type> <perm> [ <user> [ <group> [ <seclabel> ] ] ]
:
- 创建一个名为
/dev/socket/<name>
的 socket 并且将其传给创建的进程 <type>
必须为 “dgram”、”stream” 或者 “seqpacket”<User>
和<group>
默认为 0<seclabel>
是这个 socket 的 SELinux 安全上下文,其默认为这个 service 的 SELinux 安全上下文
- 创建一个名为
四、Commands
一些常用的 commands 如下所示:
bootchart_init
:如果配置过则开启 bootchartingchmod <octal-mode> <path>
:改变文件访问权限chown <owner> <group> <path>
:改变文件 owner 和 groupclass_start <serviceclass>
:启动指定 class 的所有 servicesclass_stop <serviceclass>
:停止并且关闭指定 class 的所有运行中的 servicesclass_reset <serviceclass>
:停止指定 class 的所有运行中的 services,但是不关闭,之后可以通过 class_start 重新启动它们exec [ <seclabel> [ <user> [ <group> ]* ] ] -- <command> [ <argument> ]*
:fork 并且执行给定参数的 command,一个命令执行完之前其他的不会被执行。<seclabel>
可以为 - 表示默认
五、Imports
import 关键字不是一个 command,它更像是自己的一个部分并且其在包含它的 .rc 文件被解析完成后被处理,其格式为:
import <path>
:解析一个 init 配置文件,扩展现在的配置,如果<path>
是一个目录,目录中的每个文件都会被当作一个配置文件来解析,嵌套的目录不会被解析。
更多详情请查看 /system/core/init/readme.txt
文件