Android init.rc详解
init.rc的代码目录在/Project14_1218/LA.QSSI.14.0.r1/LINUX/android/system/core/rootdir/,该文件是由init进程解析,来初始化和启动PropertyService,启动zygote和servicemanager进程。
1 概要
/system/etc/init/hw/init.rc是主rc文件,在init进程加载主rc文件之后,会自动加载位于/system/etc/init/
、/system_ext/etc/init/
、/vendor/etc/init/
、/odm/etc/init/
和 /product/etc/init/
目录下的所有 .rc
文件。
分区 | 谁负责 | 示例 |
---|---|---|
/system/etc/init/ | AOSP 团队 | 核心 Android 服务,例如surfaceFlinger,MediaService,logd等 |
/vendor/etc/init/ | 芯片厂商(如 Qualcomm) | 相机 HAL、DSP 服务 |
/odm/etc/init/ | 设备厂商(如 Xiaomi) | 定制后台服务 |
/product/etc/init/ | 产品定制(如 Google 服务) | GMS、Pixel 特有服务 |
- 每个服务都有各自的.rc文件,两者在同一个分区
- 位于system,vendor,odm分区上的所有服务的二进制可执行文件,都应该在其对应分区的/etc/init/目录下定义一个对应的.rc文件。(即每个服务都有各自的.rc文件,两者在同一个分区)。
- 相比使用单一、庞大的init.rc文件,这种拆分.rc文件根据需要加载,服务可独立打包,避免冲突。
- .rc文件何时被加载
- init进程在执行mount_all /system 或者mount_all /vendor分区之后,会自动扫描分区下的/etc/init/目录下的所有的.rc文件。
- 以logcatd.rc为例
- logcatd.rc在/system/etc/init下,logcatd的可执行文件也在/system/bin/目录下,两者都在/system/分区。
2. logcatd.rc和Android.bp的源码在目录: /Project14_1218/LA.QSSI.14.0.r1/LINUX/android/system/logging/logcat/
在Android.bp中使用init_rc属性来配置logcatd.rc文件。
cc_binary {name: "logcat",cflags: ["-Wall","-Wextra","-Werror","-DANDROID_BASE_UNIQUE_FD_DISABLE_IMPLICIT_CONVERSION=1",],shared_libs: ["libbase","libprocessgroup",],static_libs: ["liblog"],logtags: ["event.logtags"],srcs: ["logcat.cpp",],
}sh_binary {name: "logcatd",src: "logcatd.sh",
}sh_binary {name: "logpersist.start",src: "logpersist",init_rc: ["logcatd.rc"],required: ["logcatd"],symlinks: ["logpersist.stop","logpersist.cat",],
}
-
sh_binary:定义一个shell脚本可执行文件。
- name: 定义模块的名字
- src: 定义该模块的源文件
- init.rc:定义依赖的rc文件,该文件会被Build到/system/etc/init/目录下
- required: 定义依赖的模块
- symlinks:为当前模块创建两个符号链接(软链接),即
logpersist.stop
→ 指向logpersist.start,logpersist.cat
→ 指向logpersist.start。
2 init.rc的语法
Android Init Language主要有Actions,Commands,Services,Options和Imports五部分组成。
2.1 Actions
Actions被称为是一组commands的序列,它有一个trigger,用来决定该Action何时被执行。当与Action的trigger相匹配的Event发生时,Action会被加入到执行队列的队尾,然后按照command顺序执行。
on <trigger> [&& <trigger>]*<command><command><command>eg:
on zygote-start && property:ro.crypto.state=unsupportedwait_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
2.2 Trigger
Trigger | 含义 |
---|---|
on Boot | 系统引导时触发 |
on early-init | 早期init时触发 |
on init | init进程启动后触发 |
on late-init | 在完成初始化后触发,但在启动第一个Service之前 |
on early-fs | 在早期file system挂载阶段触发,主要用于start vold,vold是负责外部存储和内部存储的守护进程,负责挂载,卸载,加密,数据检查点机制。 |
on fs | vold已启动,可进行分区挂载。挂载非first-stage和latemount的分区 |
on post-fs | 在基本文件系统mount后,但在/data分区挂载之前触发 |
on post-fs-data | 在/data分区挂载后触发 |
on property:<name>=<value> | 当属性值等于value时触发,eg: on property:sys.boot_completed=1 |
2.3 Services
Service是初始化启动和退出时重启的程序。
service <name> <pathname> [ <argument> ]*<option><option>...
eg: 以on early-fs阶段启动的vold守护程序的定义为例:
service vold /system/bin/vold \--blkid_context=u:r:blkid:s0 --blkid_untrusted_context=u:r:blkid_untrusted:s0 \--fsck_context=u:r:fsck:s0 --fsck_untrusted_context=u:r:fsck_untrusted:s0class coreioprio be 2task_profiles ProcessCapacityHighshutdown criticalgroup root reserved_diskuser rootreboot_on_failure reboot,vold-failed
2.4 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。