Android init.rc详解3
关于Android Init的详解,关于Action,Service,Trigger的请参考Android init.rc详解1,关于Options的请参考Android init.rc详解2,本章将介绍常见的Commands。
1 Commands
-
bootchart [start|stop]
- 启动或停止bootcharting(系统启动性能分析),bootcharting只有在文件
/data/bootchart/enabled
存在时才会激活,斗则将不执行任何操作。- bootchart是一个收集和分析Android系统启动过程性能数据的工具,通过采样CPU、I/O、进程活动等信息,生成可视化的启动时序图(
.png
或.svg
),帮助开发者优化开机时间。bootchart start
:在启动早期(如on init
阶段)调用,启动数据采集。bootchart stop
:在启动后期(如on property:sys.boot_completed=1
)调用,停止采集并生成日志。- init.rc中使用该command的举例:
on post-fs-data# Start bootcharting as soon as possible after the data partition is# mounted to collect more data.mkdir /data/bootchart 0755 shell shell encryption=Requirebootchart starton property:sys.boot_completed=1bootchart stop# Setup per_boot directory so other .rc could start to use it on boot_completedexec - system system -- /bin/rm -rf /data/per_bootmkdir /data/per_boot 0700 system system encryption=Require key=per_boot_refsetprop ro.vendor.qti.per_boot_created 1
Android 系统的关键启动时间指标(如
bootanimation
显示、sys.boot_completed=1
)主要取决于:
class_start main
class_start late_start
- 关键服务(如
zygote
、system_server
)的启动速度。
-
chmod <octal-mode> <path>
- 更改指定文件或者目录的访问权限(读/写/执行),使用8进制表示法。
- 使用举例:
# set system-background to 0775 so SurfaceFlinger can touch it chmod 0775 /dev/cpuset/system-backgroundchmod 0664 /dev/cpuset/foreground/tasks chmod 0664 /dev/cpuset/background/tasks chmod 0664 /dev/cpuset/system-background/tasks chmod 0664 /dev/cpuset/top-app/tasks
-
chown <owner> <group> <path>
- 改变文件的所有者和用户组。
- 使用举例
# change permissions for all cpusets we'll touch at runtime chown system system /dev/cpuset chown system system /dev/cpuset/foreground chown system system /dev/cpuset/background chown system system /dev/cpuset/system-background
✅ 总结
指令 | 作用 | 典型用途 | 注意事项 |
---|---|---|---|
bootchart [start|stop] | 控制启动性能分析 | 优化开机时间 | 需手动创建 /data/bootchart/enabled 启用 |
chmod <mode> <path> | 修改文件权限 | 设置可执行、保护敏感文件 | 使用八进制权限,最小权限原则 |
chown <owner> <group> <path> | 修改文件所有者和组 | 确保服务能访问资源 | 与 chmod 配合使用 |
-
class _start <serviceclass>
- 启动指定类别(service class)的所有服务,前提是这些服务尚未运行。将同一类别的service集中管理,便于延迟启动或者统一控制。
- 他是一个批量启动服务的指令,常见的service class由
service class 值 含义 main 系统运行所必需的核心服务:zygote, bluetoothbd, storaged,
core
核心服务,servicemanager, console,ueventd, bootanim late_start 非关键、耗时或可延迟的服务(优化启动时间的关键,可以缩短sys.boot_completed时间) early_hal
需要在main之前启动的服务 hal 指Android HAL层的服务,用于与底层通信。 charger
和充电有关的service,例如charger,hw-health-service,在on charger触发的services
-
class_stop <serviceclass>
- 关闭指定类型的services。
- 使用举例
# Healthd can trigger a full boot from charger mode by signaling this # property when the power button is held. on property:sys.boot_from_charger_mode=1class_stop chargertrigger late-init
-
class_restart [ --only--enabled ] <serviceclass>
- 重启指定类别的所有services。
- 如果指定了--only--enabled,则跳过被禁用的服务(即disabled修饰的service)。
- 如果没有指定该选项,则会尝试重启该类别下的所有服务(包括disabled和oneshort修饰的service),如果服务正在运行,则先stop,然后再start;如果服务没运行,直接start。
✅ 总结
指令 | 作用 | 是否阻塞 | 典型触发时机 |
---|---|---|---|
class_start <class> | 启动指定类别中尚未运行的服务 | 否(异步) | on boot 、on property: |
class_stop <class> | 停止指定类别中正在运行的所有服务 | 否(异步) | 用户切换、省电模式、调试 |
class_restart [--only-enabled] <class> | 先停止,再重新启动该类所有服务 | 否(异步) | 错误恢复、配置重载、调试 |
-
start <service>
如果指定的服务尚未运行,则启动该服务。如果该服务已运行,start不会重复启动。
-
stop <service>
停止运行指定的service。
-
restart [ --only-if-running ] <service>
- 停止并重启一个正在运行的service。
- 如果该service处于重启过程中,则不执行任何操作;
- 如果该服务未运行,则直接启动该服务(相当于start <service>);
- 如果指定了--only-if-running选项,则仅当服务正在运行时才执行重启。如果服务未运行,则不做任何操作。
exec_start <service>
- 启动指定的服务,并暂停后续init指令,知道该service执行完成并返回。
- 他是惟一能阻塞init进程的同步指令,允许在关键启动中精确控制执行顺序,确保某些service必须启动完成。
- 使用举例:
on zygote-start && property:ro.crypto.state=unencrypted# wait OTA signature verifcation wait_for_prop odsign.verification.done 1# A/B update verifier that marks a successful boot.exec_start update_verifier_nonencryptedstart statsdstart netdstart zygotestart zygote_secondary
- A/B update:又称无缝更新,设备上由两套系统分区:A和B,当前系统允许在分区A,分区B可以后台静默更新,更新完成后,下次重启就切换到B分区。
- 首次启动B系统,则必须标记本次启动成功,如果启动成功,则B被永久标注为“新系统”,如果启动失败,下次自动切换A分区。
- A/B update verifier:检查当前系统是否时首次从新系统启动,如果是则将successful标志置为1
-
enable <servicename>
- 将一个disabled的service转化成enable,即激活service。
- enable本身不启动服务,他只是激活service,当service的启动条件满足时才会被启动,即使他是disabled。
✅ 总结
指令 | 作用 | 是否阻塞 init | 典型使用场景 | 注意事项 |
---|---|---|---|---|
start <servic> | 启动一个已定义的服务 | 否 (异步) | 正常启动服务,如 start zygote | 若服务已在运行,不会重复启动 |
stop <servic> | 停止一个正在运行的服务 | 否 (异步) | 关机、切换模式时停止服务 | 服务进程退出后不再自动重启(除非有 respawning) |
restart <servic> | 先 stop ,再 start 服务 | 否 (异步) | 配置变更后重载服务,如 restart adbd | 等价于 stop + start ,服务会短暂中断 |
exec_start <servic> | 同步执行一个 oneshot 服务,并等待其完成 | 是 (同步) | 关键初始化任务,如标记 OTA 成功、运行配置脚本 | 仅适用于 oneshot 服务;init 会等待其退出后再执行后续命令 |
enable <service> | 激活一个被 disabled 的服务,使其可被 start 或自动启动 | 否 (异步) | 根据属性动态启用服务,如 enable watchdogd when ro.boot.quiescent=1 | 服务必须先定义为 disabled ;enable 后若满足条件(如属于 main class 且已 class_start ),会立即启动 |
-
exec [ <seclabel> [ <user> [ <group> *] ] ] -- <command> [ <argument> *]
fork一个子进程并在指定的上下文(SELinux权限以及user/group)下执行。
该指令是一个同步的,会阻塞init进程。在该指令执行完成前,init将暂停后续所有指令。
参数解释 | 说明 |
---|---|
<seclabel> | SELinux 安全上下文,如 用 |
<user> | 执行用户,如 root 、system 、shell |
<group>* | 零个或多个补充组,如 inet 、log 、system |
-- | 分隔符,表示前面是执行上下文,后面是命令 |
<command> | 要执行的可执行文件路径 |
[argument]* | 命令参数,支持属性展开 ${prop} |
-
exec_backgroud [ <seclabel> [ <user> [ <group> *] ] ] -- <command> [ <argument> *]
- 与exec类似,fork一个子进程并在指定的上下文(SELinux权限以及user/group)下执行。
- 该指令是异步的,不会阻塞init,会继续执行后续指令。
✅ 总结
指令 | 是否阻塞 init | 用途 |
---|---|---|
exec | ✅ 是(同步) | 执行关键初始化任务,必须完成才能继续 |
exec_background | ❌ 否(异步) | 执行非关键、后台任务,不阻塞启动流程 |
-
setprop <name> <value>
给指定的系统属性赋值。
- 它是触发属性值为条件(on property:)的event,eg:
on property:sys.boot_completed=1bootchart stop# Setup per_boot directory so other .rc could start to use it on boot_completedexec - system system -- /bin/rm -rf /data/per_bootmkdir /data/per_boot 0700 system system encryption=Require key=per_boot_refsetprop ro.vendor.qti.per_boot_created 1
- 常见的系统属性分类:
前缀 说明 是否可写 ro.*
只读属性(Read-Only) ❌ 仅在 init
阶段可设,之后不可改sys.*
系统属性,可被 init
和系统服务修改✅ 可修改 persist.*
持久化属性,写入 /data/property/
✅ 可修改,重启后保留 ctl.*
控制属性(如 ctl.start
,ctl.stop
)✅ 触发服务控制 debug.*
调试属性 ✅ 开发者可设symlink <target> <path>
-
trigger <event>
触发一个事件,用于从一个Action执行完成后,主动触发另一个Action。
-
symlink <target> <path>
在指定path创建一个指向target的符号链接(相当于软连接,即ln -s <target> <path>)。
-
wait_for_prop <name> <value>
等待指定系统属性的值变成指定value,如果该属性值等于value,则立即执行后续命令。
他是init中用于同步控制的关键指令,setprop会触发该指令往后执行。
2 Imports
-
import <path>
- 导入一个init配置文件(或者目录下所有文件)。如果path是文件,则解析该文件;如果path是目录,则解析该目录下所有文件(不递归子目录)。
import是Android init系统实现模块化、分层话配置管理的核心机制。它允许:
将庞大的初始化配置拆分为多个.rc
文件;
按硬件、供应商、产品维度组织配置;
实现系统组件的解耦与可维护性;
支持动态加载/vendor
、/odm
等分区的配置。- 使用举例,init.rc中
import /init.environ.rc import /system/etc/init/hw/init.usb.rc import /init.${ro.hardware}.rc import /vendor/etc/init/hw/init.${ro.hardware}.rc import /system/etc/init/hw/init.usb.configfs.rc import /system/etc/init/hw/init.${ro.zygote}.rc
3 Properties
-
init.svc.<name>
- 查询指定Service name的状态。name是.rc文件中定义的Service名称。
- 当每个Service的状态发生便后时,init都会更新对应的init.svc.<name>的属性值。
eg: 查询某个Service的状态:adb shell getprop init.svc.zygote
- 服务的状态值类型有:
状态值 说明 running
服务正在运行(主进程已启动且未崩溃) stopped
服务已停止(未运行,且不是因为崩溃) restarting
服务正在重启(通常因崩溃后由 init
重启)stopping
服务正在停止过程中(收到 SIGTERM
,但进程尚未退出)disabled
服务被禁用(通过 setprop init.svc.<name> disabled
)invalid
服务未定义或路径无效(如可执行文件不存在)
-
ctl. [ <target>_ ] <command> <value>
- 该类属性是Android init用于远程控制Service生命周期和行为的“控制通道”。它允许系统其他组件通过设置属性来间接执行start/stop等。
- <target>是可选的,指定匹配的Service(当前只支持target取值Interface),注意“_”不要缺失;
- <command>是要执行的指令,前边1 Command部分介绍的指令集,常见的有start/stop
- <value>可以是Servicename,如果是Interface,对于AIDL,则value是aidl/instance;对于HIDL,则value是package::Interface/instance。
- 使用举例:
setprop ctl.restart vendor.power-hal-aidl setprop ctl.interface_restart android.hardware.power@1.0::IPower/default
4 Boot Timing
init进程在启动过程中会精确记录关键结算的时间戳和耗时,并将其写入只读属性ro.boottime.*中。
属性 含义 单位 说明 ro.boottime.init
第一阶段 init
启动的时间点ns 从 CLOCK_BOOTTIME
开始到init
进程开始执行的时间ro.boottime.init.first_stage
第一阶段 init
执行耗时ns 通常指 ramdisk
中的init
执行时间(如设备树解析、挂载/dev
等)ro.boottime.init.selinux
SELinux 策略加载与转换耗时 ns 包括 load_policy
、restorecon
等操作ro.boottime.init.modules
内核模块加载耗时 ms init
执行insmod
或modprobe
加载.ko
文件的总时间ro.boottime.init.cold_boot_wait
等待 ueventd
完成冷启动设备发现的耗时ns init
等待ueventd
发出coldboot_done
事件的时间