Android init.rc详解2
上一章节的Android init.rc 详解1介绍了.rc中Actions中常见的Trigger/Service,本章节介绍修饰Service的Options和Command。
1 Options
Options是用来修饰Services,指定how和when初始化运行这些services。
-
class <name> [ <name>\* ]
- 指定Service所属的类别class,同一个class name的所有服务可以一起启动或者停止。如果未指定class的service,则默认在“default”类下。
- 第二个name一般用于对服务进行分组。
- 常见的class分组有:core, main
-
critical [window=<fatal crash window mins>] [target=<fatal reboot target>]
- 指定Service是一个设备关键型的服务,fatal crash window mins默认值4分钟,fatal reboot target默认值bootloader,还可取值recovery,shutdown(关机),coldboot(正常重启系统)。
- 当该service在4min中崩溃退出超过4次,或者系统启动完成前崩溃多次,则设备会进入bootloader(fastboot)模式。
- 防止底层关键service反馈crash导致设备无法使用,并提供一种“安全退出”机制,引导用户进入可修复状态(刷机,恢复出厂设置,重启)。
-
disabled
指定Service不随着所属class自动启动,必须通过服务名(eg: start vold)或者接口名显式启动。
-
group <groupname> [<groupname>\*]
- 在执行该service之前,切换到指定的groupname。
- 第一个组名是必须的,代表主组,后边的组名用于设置service的补充组。当前默认组为root。
- 常见系统组及其用途
组名 用途 root
超级权限,可访问几乎所有设备和文件(不推荐滥用) system
系统服务常用组 shell
adb shell 用户所属组 net_raw
允许创建 RAW 套接字(如 ping、tcpdump) inet
网络访问权限 sdcard_r
/sdcard_rw
外部存储读写权限 graphics
GPU、SurfaceFlinger 相关权限 camera
访问摄像头设备节点 input
读取输入设备(如 /dev/input/event*
)常见系统组及其用途
-
interface <interfacename> <instance name>
- 将service与其提供的AIDL或者HIDL服务接口关联起来。该机制用于让servicemanager(AIDL)或hwservicemanager(HIDL)能够按需懒加载启动服务(lazy start),即如果该服务未运行,servicemanager会自动触发init启动该服务。
- 当一个service提供多个接口时,需要多次使用interface。
- HIDL 接口:interface <package>@<version>::<interface> <instance_name>
eg:interface vendor.foo.bar@1.0::IBaz default
- AIDL 接口:
interface aidl <instance name>
AIDL 接口的instance name
是注册到servicemanager
中的名称,可通过adb shell dumpsys -l
查看所有已注册的 AIDL 服务列表。- 配合disabled使用,实现懒加载。
service vendor.myhal.camera@2.0 /vendor/bin/hw/camera@2.0-serviceclass haldisabledinterface vendor.myhal.camera@2.0::ICameraProvider default
该service(vendor.myhal.camera@2.0)不会自动启动。
当应用打开相机时,ICameraProvider.getService()
触发 → 自动拉起该Service。
-
ioprio <calss> <priority>
为Service设置I/O优先级(IO priority)和I/O优先级类(IO priority class)。
- class取值:“rt”-实时(最高优先级,IO请求优先处理),"be"-尽力而为(默认,优先级有priority的值决定),“idle”-空闲(最低优先级,仅当系统无其他IO请求时才执行)。
- priority:必须是0-7的整数,0优先级最高,7最低。
-
namespace <pid|mnt>
为服务创建独立的PID命名空间和mount命名空间,实现进程或文件系统的隔离。init无法直接管理该服务的子进程,通常用于生命周期明确、自我管理的服务。
-
oneshot
当该Service退出时,init不会重启它。核心关键服务不能用oneshot修饰。
-
onrestart <command>
当该Service被重启时,执行onrestart后的指令。
eg: 当surfaceflinger服务重启时,要重启zygote
///Project_14/LA.QSSI.14.0.r1/LINUX/android/frameworks/native/services/surfaceflinger/surfaceflinger.rc service surfaceflinger /system/bin/surfaceflingerclass core animationuser systemgroup graphics drmrpc readproccapabilities SYS_NICEonrestart restart --only-if-running zygotetask_profiles HighPerformancesocket pdx/system/vr/display/client stream 0666 system graphics u:object_r:pdx_display_client_endpoint_socket:s0socket pdx/system/vr/display/manager stream 0666 system graphics u:object_r:pdx_display_manager_endpoint_socket:s0socket pdx/system/vr/display/vsync stream 0666 system graphics u:object_r:pdx_display_vsync_endpoint_socket:s0
-
oom_score_adjust <value>
- 设置该Service的子进程的/proc/self/oom_score_adj为指定值,取值在-1000到1000之间。该值影响在内存不足时进程被kill的优先级。
- 值越小,被kill的概率越低。保护critical进程,避免因内存不足被回收。
-
priority <value>
设置Service的CPU调度优先级(scheduling priority,即nice值),其值必须在-20到19之间,默认优先级在0,数值越小,优先级越大。
-
reboot_on_failture <target>
- 如果该Service启动失败,或者程序退出的信号类型不是CLD_EXITED(子进程正常退出),而是列入SIGSEGV、SIGKILL等,则使用指定的target重启系统。
<target>
支持的目标格式:与sys.powerctl
一致,常见值包括:
target 值 含义 reboot
正常重启系统 reboot,bootloader
重启进入 Fastboot 模式 reboot,recovery
重启进入 Recovery 模式 reboot,fastboot
同 bootloader
(较新命名)shutdown
关机 reboot,fastboot-unicorn
厂商自定义模式(如小米的“EDL”)
-
setenv <name> <value>
设置Service的环境变量。
-
shutdown <shutdown_behavior>
- 定义Service在系统关机或者重启过程中的行为,例如是否立即终止。
- <behavior>的值包括
behavior值 含义 不设置值,默认空 默认,系统进入关机流程时,iinit会向所有服务发送:
SIGTERM
(请求优雅退出)等待一段时间(通常几秒)
发送
SIGKILL
(强制终止)critical 在关机初期,该Service不会立即被kill,允许继续运行,关机流程超时会强制杀死所有进程。
如果该Service未启动运行,init会先启动,然后再进入关机流程
-
capabilities [ <capability> * ]
为该Service设置其能力(即权限),实现精细化授权。
常见capability取值由:
capability 值 含义 NET_ADMIN
配置网络接口(如设置 IP、路由) SYS_TIME
修改系统时间 CHOWN
更改文件所有者 DAC_OVERRIDE
绕过文件读写权限检查 SYS_NICE
调整进程优先级(如 setpriority
)SETPCAP
设置自身或其他进程的能力(高危!)
-
socket <name> <type> <perm> [ <user> [ <group> [ <seclabel> ] ] ]
- 创建一个名为
/dev/socket/<name>
的 UNIX 域套接字(UNIX domain socket),并在服务启动时将其文件描述符(fd)传递给该进程。Socket是用来进行进程间通信的。- 参数详解
参数 说明 <name>
套接字名称,最终路径为 /dev/socket/<name>
。例如socket adbd stream 660
→/dev/socket/adbd
<type>
套接字类型:<br>• dgram
:UDP 风格,无连接,数据报<br>•stream
:TCP 风格,面向连接,字节流<br>•seqpacket
:有序、可靠、基于消息的数据包(类似dgram
但保证顺序)<perm>
套接字文件的权限(八进制, rwx-三个用户类),如 660
、666
、777
<user>
套接字所有者用户,默认 0
(root)<group>
套接字所属组,默认 0
(root)<seclabel>
SELinux 安全上下文,如 u:object_r:adbd_socket:s0
-
task_profiles <profile> [ <profile> * ]
- 设置任务(task)性能配置文件。在 Android U (14)之前:这些配置文件仅应用于服务的主线程(main thread)。从 Android U 及以后版本开始:这些配置文件将应用于整个服务进程的所有线程。
- 该属性旨在取代writepid选项,后者是用于将进程(或线程)移动到特定的 cgroup(控制组)中,但由于需要具体的cgroup路径,设备差异大,难以维护,因此启用。writepid的使用,以蓝牙举例:
service vendor.bluetooth-1-0-qti /vendor/bin/hw/android.hardware.bluetooth@1.0-service-qti-lazyinterface android.hardware.bluetooth@1.0::IBluetoothHci defaultoneshotdisabledclass halcapabilities BLOCK_SUSPEND NET_ADMIN SYS_NICEuser bluetoothgroup bluetooth system wakelock oem_2901 net_raw oem_2912writepid /dev/stune/foreground/tasks
- <profile>的取值不是枚举的硬编码,而是由系统通过task_profiles.json配置文件定义。我们项目里源码路径在/Project_14/LA.QSSI.14.0.r1/LINUX/android/
system/core/libprocessgroup/profiles/task_profiles.json下,以下是部分profile的定义:"Profiles": [{"Name": "HighEnergySaving","Actions": [{"Name": "JoinCgroup","Params":{"Controller": "cpu","Path": "background"}}]},... {"Name": "NormalPerformance","Actions": [{"Name": "JoinCgroup","Params":{"Controller": "cpu","Path": "system"}}]},{"Name": "ServicePerformance","Actions": [{"Name": "JoinCgroup","Params":{"Controller": "cpu","Path": "system-background"}}]},{"Name": "HighPerformance","Actions": [{"Name": "JoinCgroup","Params":{"Controller": "cpu","Path": "foreground"}}]},{"Name": "MaxPerformance","Actions": [{"Name": "JoinCgroup","Params":{"Controller": "cpu","Path": "top-app"}}]},{"Name": "RealtimePerformance","Actions": [{"Name": "JoinCgroup","Params":{"Controller": "cpu","Path": "rt"}}]},{"Name": "CameraServicePerformance","Actions": [{"Name": "JoinCgroup","Params":{"Controller": "cpu","Path": "camera-daemon"}}]},{"Name": "AudioAppPerformance","Actions" : [{"Name" : "JoinCgroup","Params" :{"Controller": "schedtune","Path": "audio-app"}}]} }
2 Command
-
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会触发该指令往后执行。