Android 源码 .rc 语法详解

3 阅读4分钟

1. 引言

在 Android 系统中,.rc 文件是 init 进程的启动配置文件,它定义了系统启动过程中需要创建的服务、执行的动作、设置的系统属性等。理解 .rc 语法是阅读 Android 源码、定制系统启动流程的基础。本文将系统梳理 .rc 文件的语法规则,并结合源码实例进行讲解。

2. .rc 文件概述

.rc 文件是 Android init 进程解析的脚本文件,采用类似 C 语言的行式语法。它由若干语句组成,每条语句以关键字开头,后跟参数,语句之间以换行分隔。

2.1 文件位置

  • 系统核心服务:/system/core/rootdir/init.rc
  • 硬件相关:/device/<厂商>/<设备>/init.<设备>.rc
  • 分区相关:/system/etc/init/ 目录下的 .rc 文件

2.2 基本结构

# 注释以 # 开头

on <触发器>
    命令1
    命令2

service <服务名> <可执行文件路径>
    <选项>

3. 基础语法元素

3.1 注释

以 # 开头,支持行尾注释:

# 这是注释
service zygote /system/bin/app_process  # 行尾注释

3.2 续行

使用反斜杠 \ 进行续行:

on boot
    setprop ro.boot.hardware \
        qcom

3.3 关键字

.rc 文件的核心关键字分为三类:

类别关键字
动作on、service
命令start、stop、setprop、mkdir、chmod、chown、mount、write、exec、symlink、insmod 等
选项class、user、group、oneshot、disabled、socket、seclabel、critical 等

4. on 触发器与动作

on 语句定义了一组在特定触发条件下执行的命令:

on <触发器>
    命令

4.1 常见触发器

触发器触发时机
early-initinit 进程早期初始化
initinit 进程主初始化阶段
boot系统属性 ro.boot.bootreason 设置后
property:<属性名>=<值>指定属性被设置时
post-fs文件系统挂载完成后
post-fs-datadata 分区挂载完成后
zygote-startzygote 启动前

4.2 示例

on boot
    setprop sys.usb.config none
    start servicemanager
on property:sys.boot_completed=1
    start bootanim

5. service 服务定义

service 语句定义一个由 init 管理的守护进程:

service <服务名> <可执行文件> [参数...]
    <选项>

5.1 示例

service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
    class main
    user root
    group root readproc
    socket zygote stream 660 root system
    seclabel u:r:zygote:s0

5.2 常用选项

选项说明
class <名称>服务所属类别,可用 class_start 批量启动
user <用户名>运行服务的用户
group <组名>运行服务的组
oneshot服务退出后不自动重启
disabled服务默认不启动,需手动 start
socket <名称> <类型> <权限> <用户> <组>创建 socket
seclabel <标签>设置 SELinux 标签
critical服务崩溃导致系统重启
onrestart <命令>服务重启时执行的命令

6. 常用命令详解

6.1 属性操作

setprop <属性名> <值>
getprop <属性名>

6.2 文件系统操作

mkdir /data/local 0755
chmod 0755 /system/bin/foo
chown root system /dev/foo
mount ext4 /dev/block/mmcblk0p1 /data
symlink /system/etc/foo /etc/foo

6.3 服务控制

start <服务名>
stop <服务名>
class_start <类别名>
class_stop <类别名>

6.4 执行命令

exec /system/bin/foo --arg
exec_start <服务名>

6.5 写入文件

write /sys/class/leds/lcd/brightness 100

7. 完整实例分析

以下是一个典型的自定义服务 .rc 文件:

# 自定义守护进程
on property:persist.demo.enable=1
    start demo_service

service demo_service /system/bin/demo_daemon
    class main
    user system
    group system
    oneshot
    seclabel u:r:demo_daemon:s0
    socket demo stream 0660 system system

7.1 解析

  1. 当属性 persist.demo.enable 被设置为 1 时,触发 start demo_service。
  2. demo_service 以 system 用户身份运行,属于 main 类别。
  3. 服务退出后不自动重启(oneshot)。
  4. 创建名为 demo 的流式 socket,权限 0660。

8. 源码中的实际应用

在 Android 源码中,init.rc 位于 system/core/rootdir/ 目录。以 zygote 服务为例:

service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
    class main
    user root
    group root readproc
    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
    onrestart restart wificond

这段配置表明:zygote 属于 main 类别,以 root 身份运行,创建 zygote socket,并在重启时联动重启多个媒体相关服务。

9. 调试与验证

9.1 查看服务状态

adb shell ps -A | grep <服务名>

9.2 手动启动服务

adb shell start <服务名>

9.3 查看 init 日志

adb logcat -s init

9.4 检查语法错误

adb shell init --help

10. 总结

.rc 文件是 Android 启动流程的核心配置,掌握其语法有助于:

  • 理解系统启动顺序
  • 定制开机服务
  • 调试启动问题
  • 阅读和修改 AOSP 源码

建议读者结合 system/core/init/ 目录下的解析器源码(parser.cpp、service.cpp)深入理解 .rc 的解析逻辑,从而更全面地掌握 Android 启动机制。