1. 背景:
在init.rc文件中定义着许多系统启动需要执行的指令,主要包含action、commands、service、options等。启动后定义着开机启动时尤为重要的进程,例如zygote、uevent等。
Android init.rc语法参考:android.googlesource.com 或 system/core/init/README.md
2. init.rc语法:
在Android的init.rc文件中,主要有五个类型:
- Action(动作)
- Commands(指令)
- Services(服务)
- Options(选项)
- Imports(引入)
接下来依次分析
2.1 Action
2.1.1 语法
Action定义了指令(Commands)执行的序列。通常动作有一个触发器(trigger),用于确定什么时候执行该Action。当一个事件与动作触发器匹配时,该Action会被添加到待执行的队列尾部,除非该Action已经在队列中。
队列中的每个Action都会按照顺序出队,该Action的每个Command也会按照顺序执行。
Action的格式如下:
on <trigger> [&& <trigger>]*
<command>
<command>
<command>
例如:如果有一个文件的Action如下:
on boot
setprop a 1
setprop b 2
on boot && property:true=true
setprop c 1
setprop d 2
on boot
setprop e 1
setprop f 2
并且假设当boot完成时,property:true==ture。那么以上Commands实际上的执行次序为:
setprop a 1
setprop b 2
setprop c 1
setprop d 2
setprop e 1
setprop f 2
2.1.2 实例
以init.rc(system/core/init/init.rc)中的一段为例
on property:sys.boot_from_charger_mode=1
class_stop charger
trigger late-init
解析:当property:sys.boot_from_charger_mode=1时,停止charger服务,触发late-init事件。class_stop charger 和 trigger late-init 是两个command
2.2 Commands
2.2.1 语法
Commands由两个部分组成,分别是触发器(trigger)和Command(指令)组成。
其中触发器(trigger)如下表所示:
| 触发器 | 描述 |
|---|---|
| < name > = < value > | 当属性< name >满足特定< value >时触发 |
| device-added-< path> | 当设备节点添加/删除时触发此事件 |
| service-exited-< name > | 当指定的服务< name >存在时触发 |
指令(Command)如下所示:
| command | 描述 |
|---|---|
| bootchart[start|stop] | 开启/结束 bootcharting |
| chmod | 修改文件权限 |
| chown | 修改文件所有者和所在组 |
| class_start < serviceclass > | 启动由< servicesclass >类名指定的所有相关服务,如果他们不存在运行状态的话 |
| class_stop < serviceclass > | 停止所有由< serviceclass >指定的服务,如果他们当前正在运行的话 |
| class_reset | 停止所有service指定的class |
| copy | 复制src到dst |
| domainname | 设置domain name |
| enable | 将一个被禁用的服务转换为可用状态 |
| exec < path > [< argument >]* | Fork并执行一个程序,其路径为< path >,这条命令将阻塞直到该程序启动完成,因此他有可能造成init程序在某个点不停的等待。 |
| exec_start | 启动一个给定的服务,并在它返回之前停止处理额外的初始化命令。这个命令的功能类似于exec命令,但是它使用现有的服务定义来代替执行参数向量。 |
| exec_background [ [ [ * ] ] ] -- [ * ] | Fork并执行一个程序,与exec类似。 |
| ifup < interface > | 使网络接口< interface >成功连接。 |
| import < filename > | 解析另外一个配置文件,名为< filename >,以扩展当前配置。 |
| hostname < name > | 设置主机名为< name > |
| insmod < path > | 在< path >路径上安装一个模块 |
| load_all_props | 从/system 、/vendor等加载properties |
| load_persist_props | 当/data分区不加密时加载所有properties |
| loglevel | 设置日志级别 |
| mkdir < path >[mode][owner][group] | 在< path >上新建一个目录 |
| mount_all [ ]* [--] | 挂载所有设备 |
| mount < type >< device >< dir >[mountoption] | 尝试在指定路径上挂载一个设备 |
| restart | 停止然后重启服务 |
| restorecon [ * ] | 重新存储文件名 |
| restorecon_recursive [ * ] | 递归地将名为_path_的目录树恢复到file_contexts配置中指定的安全上下文。 |
| rm | 删除文件 |
| rmdir | 删除空目录 |
| readahead <file|dir> [--fully] | 启动文件预读到页面缓存中 |
| setprop< name >< value > | 设置系统属性< name >的值< value > |
| setrlimit | 设置进程的资源限制 |
| start < service > | 这个命令将启动一个服务,如果他没有处于运行状态的话 |
| stop < service > | 这个命令将启动一个服务,如果他没有处于运行状态的话 |
| swapon_all | 激活Linux系统中交换空间 |
| symlink < target >< path > | 创建一个< path >路径的连接,目标为< target > |
| sysclktz <mins_west_of_gmt> | 指定系统时钟基准 |
| trigger < event > | 触发一个事件 |
| umount | 卸载目录 |
| verity_load_state | 用于加载dm-verity状态的内部实现细节。 |
| verity_update_state | 更新dm-verity状态 |
| wait [ ] | 轮询文件的存在时间 |
| wait_for_prop | 等待系统属性_name_变为_value_ |
| write < path >< string >[ < string >]* | 打开一个文件,并写入一个或多个字符串 |
2.2.2 实例
以init.rc(system/core/init/init.rc)中的一段为例:
on property:vold.decrypt=trigger_restart_framework
# A/B update verifier that marks a successful boot.
exec_start update_verifier
class_start main
class_start late_start
setprop service.bootanim.exit 0
start bootanim
解析:当property:vold.decrypt=trigger_restart_framework时,
- 启动 update_verifier
- 启动 main 类指定的服务
- 启动 late_start 类指定的服务
- 设置系统属性 service.bootanim.exit 为 0
- 启动 bootanim 服务
2.3 Services
2.3.1 语法
Services是init启动的程序。其语法如下:
```
service <name> <pathname> [ <argument> ]*
<option>
<option>
...
```
2.3.2 实例
以init.rc(system/core/init/init.rc)中的一段为例:
```
service flash_recovery /system/bin/install-recovery.sh
class main
oneshot
```
定义一个service,service名为flash_recovery,脚本位置为/system/bin/install-recovery.sh,为服务指定的类名为class,并且指定为oneshot(退出后不再启动)。
2.4 Options
2.4.1 语法
Options是对service的修饰符。这些修饰影响init如何以及何时运行service。
options如下:
| options | 描述 |
|---|---|
| console [] | 服务需要一个控制台 |
| critical | 这是一个对于设备来说非常重要的服务。如果这个服务在四分钟内重启超过四次,设备就会重启进入revovery模式 |
| disabled | 添加这个修饰后,服务不会自动重启 |
| setenv | 当启动进程的时候,设置系统变量_name_的值变为_value_ |
| socket [ [ [ ] ] ] | 创建一个名为/dev/socket/_name_的unix套接字,然后将他的文件描述符给启动的进程 |
| enter_namespace | 进入位于_path_类型为_type_用户空间 |
| file | 打开一个文件地址然后将他的文件描述符传递给启动的进程 |
| user | 在执行此服务之前修改为username,默认是root |
| group [ * ] | 执行服务前修改为groupname |
| capabilities [ * ] | 执行服务之前设置capabilities |
| setrlimit | 给服务提供rlimit |
| seclabel | 在service执行完成后改为seclabel |
| oneshot | service退出后不再重启 |
| class [ * ] | 为service指定类名 |
| animation class | 为开机动画和关机动画指定必要服务 |
| onrestart | service重启时指定以下指令 |
| writepid [ * ] | 当进程启动时将子进程号写入文件 |
| priority | 服务进程调度优先级 |
| namespace <pid|mnt> | 创建service时进入新的pid或者挂在命名空间 |
| oom_score_adjust | 设置子进程指定的/proc/self/oom_score_adj值 |
| memcg.swappiness | 设置子进程内存 |
| memcg.soft_limit_in_bytes | 设置子进程内存 |
| memcg.limit_in_bytes | 设置子进程内存 |
| shutdown <shutdown_behavior> | 设置服务进程的关机行为 |
2.4.2 实例
以init.rc(system/core/init/init.rc)中的一段为例:
```
service ueventd /sbin/ueventd
class core
critical
seclabel u:r:ueventd:s0
shutdown critical
```
定义一个service,service名为uevent,脚本位于/sbin/ueventd。此service指定的类名为core,critical进程,设置seclabel为u:r:ueventd:s0,标记shutdown_behavior为cirtical。
2.5 Imports
2.5.1 语法
mports用于引用配置文件,扩展当前配置。
imports的语法如下:
```
`import <path>`
```
2.5.2 实例
```
import /init.environ.rc
```
解析:引入 /init.environ.rc 文件