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/。