rc文件

rc文件由安卓初始化语言编写,是配置文件,不是程序,不会被编译/链接。可用于初始化系统服务、设置属性、创建系统资源等操作。rc文件在Init进程中完成扫描、解析、加载、执行等操作。

官方文档为system/core/init/README.md

语法

  • 语法组成

    • 由五部分组成

      1. Action(行为)
      2. Commands(命令)
      3. Services(服务)
      4. Options(选项)
      5. 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)。

    1. 属性触发器

      属性变为指定的属性值时触发。

    2. 事件触发器

      通过QueueEventTrigger函数(C++),或trigger command触发。

      1
      2
      on 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命令类似,只不过启动对象是已声明的service
    export <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

    1. Action是一系列Command的集合;
    2. 每个Action拥有一个Trigger,Trigger用来决定Action什么时候被执行;
    3. 当Trigger被触发,相应的Action会被添加到任务队列中(队尾插入),如果已在队列中则忽略;
    4. Action中的每条命令,将会被顺序取出并执行。
    • 语法格式

      1
      2
      3
      on <trigger> [&& <trigger>]*
      <command>
      <command>
    • 例子

      1
      2
      on 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, adbd
    setenv <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>,默认是root
    writepid <file> [ <file>\* ] 将创建子进程时,将其pid写入指定的文件
  • Services

    Services指一些Programs(程序),这些程序由Init启动/重启。

    • 语法格式

      1
      2
      3
      4
      service <name> <pathname> [<argument>]*
      <option>
      <option>
      <option>
    • 例子

      1
      2
      3
      4
      service gocsdk /system/bin/gocsdk
      class main
      disabled
      oneshot

      gocsdk是服务的名字,这个可执行文件的位置在/system/bin/gocsdk。disabled、oneshot是options,用来描述service的特点。

  • Import

    引入其他rc文件。

    • 语法格式

      1
      import <path>
    • 如果path传入的是一个目录,则解析该目录下全部配置文件,非递归,嵌套目录不会被解析。

    • Init进程只在三个时间点执行import指令:

      1. 在启动过程中解析系统根目录的/init.rc,或者是ro.boot.init_rc属性指明的rc文件;
      2. 在解析完/init.rc,启动第一阶段时解析/{system,vendor,odm}/etc/init/文件;
      3. 在mount_all指令中解析/{system,vendor,odm}/etc/init/。

rc文件
https://citrus-maxima.github.io/2024/03/10/rc文件/
作者
柚子树
发布于
2024年3月10日
许可协议