rc文件
rc文件由安卓初始化语言编写,是配置文件,不是程序,不会被编译/链接。可用于初始化系统服务、设置属性、创建系统资源等操作。rc文件在Init进程中完成扫描、解析、加载、执行等操作。
官方文档为system/core/init/README.md
。
语法
语法组成
由五部分组成
- Action(行为)
- Commands(命令)
- Services(服务)
- Options(选项)
- Imports(导入)
Comments(注释):以#开头的行,表示注释(允许前导空格)。
Section(段落/分组)
rc文件的基本单位,有三种类型:on、service、import
关键字和参数以空格分割,每个语句以行为单位。
C语言风格的反斜杠转义字符(“\”)可以用来为参数添加空格。
为了防止字符串中的空格把其切割成多个部分,需要对其使用双引号。
行尾的反斜杠用来表示下面一行是同一行。
Actions和Services暗示着一个新语句的开始,这两个关键字后面跟着的Commands或者Options都属于这个新语句。
Actions和Services有唯一的名字,如果出现和已有动作或者服务重名的,将会被当成错误忽略掉。
on
on early-init
:Init之前,加载完所有rc文件后即执行,init.rc在early-init执行的是start ueventd
。on init
:在/init.conf(启动配置文件)被装载之后,加载propety各项属性文件之前执行,在Init变为property service之前都属于Init阶段。late-init
:初始化之后执行。on early-boot
:启动属性服务后即执行。on boot
:boot的时候执行。on property:xxxxx=x
:当某个属性设置为预期值时执行。device-added-<path>
:指定设备被添加时触发。device-removed-<path>
:指定设备被移除时触发。service-exited-<name>
:在特定服务(service)退出时触发。
Trigger
触发器,本质上是字符串,用于匹配包含该字符串的事件(Event)。
属性触发器
属性变为指定的属性值时触发。
事件触发器
通过QueueEventTrigger函数(C++),或trigger command触发。
1
2on xxx:
trigger sss
Trigger可以由多个属性触发器 + 一个事件触发器组成。
Command
命令。
命令 描述 `bootchart [start stop]` chmod <octal-mode> <path>
设置文件权限 chown <owner> <group> <path>
设置文件所有者和所有组 class_start <serviceclass>
对于所有属于该class的service,若没有在运行中,则启动它们 class_stop <serviceclass>
对于所有属于该class的service,若在运行中,则终止它们,且将状态改为不可用(disabled) class_reset <serviceclass>
终止,但不设置成disabled class_restart [--only-enabled] <serviceclass>
重新启动指定类的所有服务。如果指定了“–only-enabled”,则跳过禁用的服务。 copy <src> <dst>
复制文件,可用于二进制、大量文件场景。复制后文件权限为0600,若目标文件已存在则终止操作 copy_per_line <src> <dst>
逐行复制文件 domainname <name>
设置域名 enable <servicename>
将disabled的service设置为enable状态,如果service预期运行,则运行它 exec [ <seclabel> [ <user> [ <group>\ ] ] ] -- <command> [ <argument>\*]
创建进程(fork)并且执行命令,可选参数为seclabel(安全上下文,security context),用户和组。Init进程会阻塞直至命令运行结束 exec_background [ <seclabel> [ <user> [ <group>\* ] ] ] -- <command> [ <argument>\* ]
与“exec”命令的处理方式类似。不同之处在于,Init 不会停止执行命令,直到进程退出“exec_background” exec_start <service>
启动一个已声明的service,并阻塞Init直至该service运行结束。它与 exec
命令类似,只不过启动对象是已声明的serviceexport <name> <value>
设置global域下的环境变量,所有进程(因为它们都是Init的子进程)都可与读取到该变量 hostname <name>
设置host name ifup <interface>
启用网络 insmod [-f] <path> [<options>]
安装module到路径path interface_start <name>
interface_restart <name>
interface_stop <name>
找到提供接口name的服务(如果存在),并分别对其运行“start”、“restart”或“stop”命令 load_exports <path>
打开位于path的文件,并导出其中声明的全局环境变量 load_persist_props
当/data被解密时,加载persistent属性。在默认的init.rc中会执行该逻辑 loglevel <level>
设置内核日志级别 mark_post_data
/data被挂载后标记point mkdir <path> [mode] [owner] [group]
创建目录,可选参数为读写权限、拥有者、组别,其默认值分别为755、root、root group mount_all <fstab> [ <path> ]\* [--<option>]
在fs_mgr-format的fstab上执行fs_mgr_mount_all,导入指定path下的.rc文件。可选参数为”early”和”late” mount <type> <device> <dir> [ <flag>\* ] [<options>]
将设备挂载到指定目录,flags包括”ro”, “rw”, “remount”, “noatime”等。options包括”barier=1”, “noauto_da_alloc”等。 perform_apex_config
挂载 APEX 后执行任务 restart [--only-if-running] <service>
停止并重新启动正在运行的服务,如果服务当前正在重新启动,则不执行任何操作,否则,它只是启动服务。如果指定了“–only-if-running”,则仅当服务已在运行时重新启动服务。 restorecon <path> [ <path>\* ]
恢复目录下的文件 restorecon_recursive <path> [ <path>\* ]
递归恢复目录下的文件 rm <path>
对于指定path调用unlink rmdir <path>
对于指定path调用rmdir `readahead <file dir> [–fully]` setprop <name> <value>
设置属性值 setrlimit <resource> <cur> <max>
设置资源的rlimit start <service>
开启service, 注意这个操作不是阻塞的,意味着start顺序不表示运行顺序,如果service之间有依赖顺序,须谨慎使用 stop <service>
停止服务 swapon_all <fstab>
在指定的fstab文件上调用fs_mgr_swapon_all symlink <target> <path>
创建符号链接 sysclktz <mins_west_of_gmt>
设置系统时钟基础值(如果是GMT则为0) trigger <event>
触发一个事件,用于action之间互相触发 umount <path>
卸载挂载在path上的文件系统 umount_all [ <fstab> ]
对给定的 fstab 文件调用 fs_mgr_umount_all verity_update_state
更新dm-verity状态并设置 adb remount 使用的 partition.mount-point.verified属性 wait <path> [ <timeout> ]
轮询指定path的文件是否存在,直到它出现或者超时,默认超时时间为5s wait_for_prop <name> <value>
等待直至属性被定义为指定值 write <path> <content>
打开path的文件并写入一个string,若文件不存在则先创建它。若文件存在则续写 Action
- Action是一系列Command的集合;
- 每个Action拥有一个Trigger,Trigger用来决定Action什么时候被执行;
- 当Trigger被触发,相应的Action会被添加到任务队列中(队尾插入),如果已在队列中则忽略;
- Action中的每条命令,将会被顺序取出并执行。
语法格式
1
2
3on <trigger> [&& <trigger>]*
<command>
<command>例子
1
2on zygote-start && property:ro.crypto.state=unsupport
start netd
Option
Option是Services的修饰符(选项),通过Option告知Init如何对待Services。
选项 描述 capabilities <capability> [<capability>\*]
当运行该service时,设置capability,capability是Linux系统中以”CAP_”为前缀的属性 class <name> [ <name>\* ]
声明service的类名,用来给service归类,所有在同一类名下的service可以被同时开启/终止。默认类名是 default
。 例如可以将开机过程中的动画service归入amination
类console [<console>]
表明service需要在console环境下使用,可选参数声明了默认console以外的环境。通常默认的console是 /dev/console
。critical [window=<fatal crash window mins>] [target=<fatal reboot target>]
这是对设备至关重要的一个服务。如果它在四分钟内退出超过四次,则设备将重启进入恢复模式。 disabled
表明service不会自动启动,必须显式地通过名字来启动 enter_namespace <type> <path>
进入位于path的type类型的命名空间 file <path> <type>
打开一个文件,并将fd传给启动的进程。type取值为”r”、”w”或者”rw” gentle_kill
此服务停止时将发送 SIGTERM 而不是 SIGKILL。200 毫秒超时后,将发送 SIGKILL。 group <groupname> [<groupbame>\*]
在执行该service前,切换组为 <groupname>
,默认是root。除了(必需的)第一个组名之外,其他组名用于设置进程的补充组(通过 setgroups())。interface <interface name> <instance name>
将此服务与其提供的 AIDL 或 HIDL 服务列表相关联 ioprio <class> <priority>
设置IO优先级 keycodes <keycode> [ <keycode>\* ]
设置将触发此服务的键码。如果同时按下与设置的键码对应的所有键,则服务将启动。通常用于启动bugreport服务。 memcg.limit_in_bytes <value>
设置子进程的memory.limit_in_bytes ,不小于0 memcg.limit_property <value>
设置子进程的memory.limit_in_bytes为指定属性的值 memcg.soft_limit_in_bytes <value>
设置子进程的memory.soft_limit_in_bytes ,不小于0 memcg.swappiness <value>
设置子进程的memory.swappiness,不小于0 `namespace <pid mnt>` oneshot
当service退出时,不主动重启 onrestart
当service重启(restart) 时,执行该command oom_score_adjust <value>
设置子进程的/proc/self/oom_score_adj ,取值范围-1000~1000 override
此service旨在覆盖具有相同名称的服务的先前定义 priority <priority>
设置service进程的优先级,范围-20~19,默认优先级是0 reboot_on_failure <target>
如果无法启动此进程,或者进程终止时退出码不是 CLD_EXITED 或状态不是“0”,使用 target中指定的目标重启系统 restart_period <seconds>
如果非一次性服务退出,它将在其开始时间加上此时间段重新启动 rlimit <resource> <cur> <max>
将给定的 rlimit 应用于服务 seclabel <seclabel>
在运行该service之前,修改 seclabel
属性,通常从rootfs启动的service会使用该选项,如ueventd, adbdsetenv <name> <value>
表明在service的进程中设置一个环境属性 shutdown <shutdown_behavior>
设置该service进程的关机行为。若未声明,当关机时该service被SIGTERM和SIGKILL信号终止。被声明为 critical
的service不会在关机期间被终止,直至完全关机。被声明为shutdown critical
的service会在关机期间启动(如果它没有在运行)sigstop
在调用 exec 之前立即将 SIGSTOP 发送到服务,用于调试 socket <name> <type> <perm> [<user>[<group>[<seclabel>]]]
启动一个名为 /dev/socket/name
的socket,并且将它的fd传给当前进程,type必须是”dgram”、”stream”、或者”seqpacket”,seclabel是SELinux的设置stdio_to_kmsg
将 stdout 和 stderr 重定向到 devkmsg_debug task_profiles <profile> [ <profile>\* ]
设置任务配置文件 timeout_period <seconds>
提供超时,超过该时间点后,服务将被终止 updatable
标记该服务可以在启动序列中稍后被 APEX 覆盖(通过“覆盖”选项) user <username>
在执行该service前,切换用户为 <username>
,默认是rootwritepid <file> [ <file>\* ]
将创建子进程时,将其pid写入指定的文件 Services
Services指一些Programs(程序),这些程序由Init启动/重启。
语法格式
1
2
3
4service <name> <pathname> [<argument>]*
<option>
<option>
<option>例子
1
2
3
4service gocsdk /system/bin/gocsdk
class main
disabled
oneshotgocsdk是服务的名字,这个可执行文件的位置在/system/bin/gocsdk。disabled、oneshot是options,用来描述service的特点。
Import
引入其他rc文件。
语法格式
1
import <path>
如果path传入的是一个目录,则解析该目录下全部配置文件,非递归,嵌套目录不会被解析。
Init进程只在三个时间点执行import指令:
- 在启动过程中解析系统根目录的/init.rc,或者是ro.boot.init_rc属性指明的rc文件;
- 在解析完/init.rc,启动第一阶段时解析/{system,vendor,odm}/etc/init/文件;
- 在mount_all指令中解析/{system,vendor,odm}/etc/init/。