参考:system/core/init/readme.txt (android init language)
init.rc名词:action,service,commands,option,trigger
1. action
一系列commands的集合,由触发器控制执行顺序
on post-fs-data
chown system system /data
chmod 0771 /data
2. commands
可执行的commands和可以使用的option在system/core/init/keywords.h中定义。
KEYWORD(chdir, COMMAND, 1, do_chdir)
KEYWORD(chroot, COMMAND, 1, do_chroot)
KEYWORD(class, OPTION, 0, 0)
KEYWORD(class_start, COMMAND, 1, do_class_start)
KEYWORD(class_stop, COMMAND, 1, do_class_stop)
KEYWORD(class_reset, COMMAND, 1, do_class_reset)
KEYWORD(console, OPTION, 0, 0)
KEYWORD(critical, OPTION, 0, 0)
KEYWORD(disabled, OPTION, 0, 0)
KEYWORD(domainname, COMMAND, 1, do_domainname)
KEYWORD(exec, COMMAND, 1, do_exec)
KEYWORD(export, COMMAND, 2, do_export)
每个commands的实现为do_commands。
3. option
option如上定义。option用来修饰service,影响service的运行。
critical(关键)
说明这是一个对于设备关键的服务。如果他四分钟内退出大于四次,系统将会重启并进入recovery(恢复)模式。
disabled(失效)
说明这个服务不会同与他同trigger(触发器)下的服务自动启动。他必须被明确的按名启动。
setenv <name> <value> (设置环境变量)
在进程启动时将环境变量<name>设置为<value>。
socket <name> <type> <perm> [ <user> [ <group> ] ]
创建一个Uinx域的名为/dev/socket/<name> 的套接字,并传递它的文件描述符给已启动的进程。<type> 必须是 "dgram"或"stream"。User 和 group默认为0。
user <username>
在启动这个服务前改变该服务的用户名。此时默认为root。当前,如果你的进程要求Linux capabilities(能力),你无法使用这个命令。即使你是root,你也必须在程序中请求capabilities(能力)。然后降到你想要的 uid。
group <groupname> [ <groupname> ]*
在启动这个服务前改变该服务的组名。除了(必需的)第一个组名,附加的组名通常被用于设置进程的补充组(通过setgroups())。此时默认为root。
oneshot
服务退出时不重启。
class <name>
指定一个服务类。所有同一类的服务可以同时启动和停止。如果不通过class选项指定一个类,则默认为"default"类服务。
onrestart
当服务重启,执行一个命令
4. service
service定义格式:
service name path args
option
重要服务举例:adbd, ril-daemon,vold,zygote
service vold /system/bin/vold
class core
socket vold stream 0660 root mount
ioprio be 2
service在代码中启动:
c++:
<span style="white-space:pre"> </span>property_set("ctl.start", "service_name");
<span style="white-space:pre"> </span>property_set("ctl.stop", "service_name");
java:
<span style="white-space:pre"> </span>SystemProperties.set
5. trigger
控制action发生,trigger发生时,action的commands依次加入到队列执行。
服务启动顺序
init_parse_config_file("/init.rc");
action_for_each_trigger("early-init", action_add_queue_tail);
queue_builtin_action(wait_for_coldboot_done_action, "wait_for_coldboot_done");
queue_builtin_action(keychord_init_action, "keychord_init");
queue_builtin_action(console_init_action, "console_init");
/* execute all the boot actions to get us started */
action_for_each_trigger("init", action_add_queue_tail);
/* skip mounting filesystems in charger mode */
if (!is_charger) {
action_for_each_trigger("early-fs", action_add_queue_tail);
action_for_each_trigger("fs", action_add_queue_tail);
action_for_each_trigger("post-fs", action_add_queue_tail);
action_for_each_trigger("post-fs-data", action_add_queue_tail);
}
queue_builtin_action(property_service_init_action, "property_service_init");
queue_builtin_action(signal_init_action, "signal_init");
queue_builtin_action(check_startup_action, "check_startup");
if (is_charger) {
action_for_each_trigger("charger", action_add_queue_tail);
} else {
action_for_each_trigger("early-boot", action_add_queue_tail);
action_for_each_trigger("boot", action_add_queue_tail);
}
/* run all property triggers based on current state of the properties */
queue_builtin_action(queue_property_triggers_action, "queue_property_triggers");
init.rc解析完成后,依次将这些trigger加入,对应的action加入队尾开始执行。
on boot
class_start core
class_start main
on boot最后class_start core & main,class 为core和main的service开始依次执行。