Android启动之配置文件分析
本篇主要包括如下内容:
init.rc语法介绍
补充说明
一、init.rc语法介绍
1,init.rc是一个可配置的初始化文件,通常定制厂商可以配置额外的初始化配置,init.%PRODUCT%.rc
2,init.rc是在$GINGERBREAD/system/core/init/init.c中读取的,它基于“行”,包含一些用空格隔开的关键字(它属于特殊字符)
3,如果关键字中有空格,处理方法类似于C语言,使用/表示转义,使用“”防止关键字被断开,另外注意/在末尾表示换行
4,#开头的表示注释
5,init.rc包含4种状态类别:Actions/Commands/Services/Options
6,当声明一个service或者action的时候,它将隐式声明一个section,它之后跟随的command或者option都将属于这个section
7,action和service不能重名,否则忽略为error
8,actions就是在某种条件下触发一系列的命令,通常有一个trigger,形式如:
on <trigger>
<command>
<command>
9,service结构如下:
service <name> <pathname> [ <argument> ]*
<option>
<option>
10,option是service的修饰词,主要包括:
critical :表示如果服务在4分钟内退出超过4次,则系统重启到recovery mode
disabled :表示服务不会自动启动,需要显示调用服务名来启动
setEnv <name> <value> :设置环境变量<name>为某个值<value>
socket <name> <type> <permission> [<user> [<group>]] :开启一个unix域的socket,名字为/dev/socket/<name> , fd值传给启动它的进程。<type>只能是dgram,stream 或 seqpacket,而<user>和<group>默认为0
user <username> :表示将用户切换为<username>, 默认情况下用户都是root。
group <groupname> :表示将组切换为<groupname>
oneshot :表示这个service只启动一次
class <name> :指定一个要启动的类,这个类中如果有多个service,将会被同时启动。默认的class将会是“default”
onrestart :当此服务重启时,执行某些命令
11,trigger主要包括:
boot :当/init.conf加载完毕时
<name>=<value> :当<name>被设置为<value>时
device-added-<path> :设备<path>被添加时
device-removed-<path> :设备<path>被移除时
service-exited-<name> :服务<name>退出时
12,命令主要包括:
exec <path> [ <argument> ]* :Fork并执行一个<path>指定的程序。这条命令将阻塞直到该程序启动完成,因此它有可能造成init程序在某个点不停的等待。
export <name> <value> :设置一个全局变量
ifup <interface> :使网络接口<interface>成功连接
import <filename> :引入另一个配置文件
hostname <name> :设置主机名<name>
chdir <directory> :切换工作目录
chmod <octal-mode> <path> :设置访问权限
chown <owner> <group> <path> :设置用户和组
chroot <directory> :设置根目录位置
class_start <serviceclass> :启动<serviceclass>类名指定的所有相关服务(如果它们不在运行状态的话)
class_stop <serviceclass> :停止类中的<serviceclass>指定的服务(如果它们当前正在运行状态)
domainname <name> :设置域名
insmod <path> :安装模块
mkdir <path> [mode] [owner] [group] :创建一个目录,并可以指定权限,用户和组
mount <type> <device> <dir> [ <mountoption> ]* :尝试在指定路径下挂载一个设备,<mountoption> 包括"ro", "rw", "remount", "noatime"
setprop <name> <value> :设置系统属性
setrlimit <resource> <cur> <max> :设置资源访问权限
start <service> :开启服务(如果它没有处于运行状态的话)
stop <service> :停止服务(如果它当前正在运行的话)
symlink <target> <path> :创建一个<path>路径的链接,目标为<target>
sysclktz <mins_west_of_gmt> :设置基准时间
trigger <event> :触发一个事件
write <path> <string> [ <string> ]* :向<path>路径的文件写入多个<string>
二、init.rc补充
1,init.rc位于/system/core/rootdir/init.rc,这里会导入各个厂商的定制.rc文件(一般位于device目录下),如下所示。
import /init.environ.rc
import /init.usb.rc
import /init.${ro.hardware}.rc
import /init.usb.configfs.rc
import /init.${ro.zygote}.rc
import /init.trace.rc
2,init进程会解析init.rc文件,如下所示。
int main(int argc, char** argv) {
if (!strcmp(basename(argv[0]), "ueventd")) {
return ueventd_main(argc, argv);
}
...
init_parse_config_file("/init.rc");
action_for_each_trigger("early-init", action_add_queue_tail);
...
action_for_each_trigger("init", action_add_queue_tail);
queue_builtin_action(mix_hwrng_into_linux_rng_action, "mix_hwrng_into_linux_rng");
char bootmode[PROP_VALUE_MAX];
if (property_get("ro.bootmode", bootmode) > 0 && strcmp(bootmode, "charger") == 0) {
action_for_each_trigger("charger", action_add_queue_tail);
} else {
action_for_each_trigger("late-init", action_add_queue_tail);
}
queue_builtin_action(queue_property_triggers_action, "queue_property_triggers");
while (true) {
...
}
return 0;
}
请注意上述代码中几个trigger的触发顺序:early-init --> init --> late-init,值得注意的是,late-init会继续触发trigger,如下所示。
on late-init
trigger early-fs //挂fstab.freescale里面的
trigger fs //挂fstab.freescale里面的
trigger post-fs //创建一堆的目录和数据
# Load properties from /system/ + /factory after fs mount. Place
# this in another action so that the load will be scheduled after the prior
# issued fs triggers have completed.
trigger load_system_props_action //加载系统属性
# Now we can mount /data. File encryption requires keymaster to decrypt
# /data, which in turn can only be loaded when system properties are present
trigger post-fs-data //创建data下面的目录
trigger load_persist_props_action //加载永久属性
# Remove a file to wake up anything waiting for firmware.
trigger firmware_mounts_complete
trigger early-boot
trigger boot //启动boot
3,boot 中会启动core服务,如下所示。
on boot
...
chown root system /sys/module/lowmemorykiller/parameters/adj
chmod 0664 /sys/module/lowmemorykiller/parameters/adj
chown root system /sys/module/lowmemorykiller/parameters/minfree
chmod 0664 /sys/module/lowmemorykiller/parameters/minfree
...
class_start core //启动所有class标记为core的服务
4,关键字class说明
基本的服务类型(class)包括三种:core(最重要的)、main(次级重要的)、late_start(不那么重要的)。这三类服务分别通过class_start, class_reset, class_stop来对统一类的服务进行统一的操作。相同类别的服务,基本上是同时启动,相互之间的延时很小。
对/system/core/rootdir/init.rc中的class core进行全局搜索,列出部分结果如下:
ueventd | /sbin/ueventd |
logd | /system/bin/logd |
healthd | /sbin/healthd |
console | /system/bin/sh |
adbd | /sbin/adbd |
servicemanager | /system/bin/servicemanager |
vold | /system/bin/vold |
surfaceflinger | /system/bin/surfaceflinger |
bootanim | /system/bin/bootanimation |
对/system/core/rootdir/init.rc中的class main进行全局搜索,列出部分结果如下:
netd | /system/bin/netd |
debuggerd | /system/bin/debuggerd |
debuggerd64 | /system/bin/debuggerd64 |
ril-daemon | /system/bin/rild |
surfaceflinger | /system/bin/surfaceflinger |
media | /system/bin/mediaserver |
bootanim | /system/bin/bootanimation |
installd | /system/bin/installd |
sshd | /system/bin/start-ssh |
zygote | /system/bin/app_process |
至此,init.rc语法已简单介绍完毕,细节需要去查看原始init.rc文件并结合解析器代码。
参考: