浅析iniit.rc脚本中的service程序不写disabled字段why会自动执行
1.ramdisk的/init.rc中,
...
on boot//在boot阶段执行
ifup lo
hostname localhost
...
class_start default //对应KEYWORD(class_start, COMMAND, 1, do_class_start)
...
service console /system/bin/sh //这个sh就是busybox或者toolbox等开源工具的一个ln -s连接
console
...
==>do_class_start
==>service_for_each_class
==>service_start_if_not_disabled
==>service_start
KEYWORD(class_start, COMMAND, 1, do_class_start)
int do_class_start(int nargs, char **args)
{
/* Starting a class does not start services
* which are explicitly disabled. They must
* be started individually.
*/
service_for_each_class(args[1], service_start_if_not_disabled);
return 0;
}
void service_for_each_class(const char *classname,
void (*func)(struct service *svc))
{
struct listnode *node;
struct service *svc;
list_for_each(node, &service_list) {
svc = node_to_item(node, struct service, slist);
if (!strcmp(svc->classname, classname)) {//执行所有classname为上面class_start default指定的default的svc程序
//所以这样service console /system/bin/sh我们的console交互程序shell -- /system/bin/sh处理来自console开发板的串口输入了,并且会将结果output输出到console开发板的串口上[luther.gliethttp]
func(svc);
}
}
}
static void service_start_if_not_disabled(struct service *svc)
{
if (!(svc->flags & SVC_DISABLED)) {
service_start(svc);
}
}
==>service_start
...
needs_console = (svc->flags & SVC_CONSOLE) ? 1 : 0;
...
pid = fork();
if (pid == 0) {
...
if (needs_console) {
setsid();
open_console();//打开console
} else {
zap_stdio();
}
...
execve(svc->args[0], (char**) svc->args, (char**) ENV);//执行函数
...
static void open_console()
{
int fd;
if ((fd = open(console_name, O_RDWR)) < 0) {
fd = open("/dev/null", O_RDWR);
}
dup2(fd, 0);
dup2(fd, 1);
dup2(fd, 2);
close(fd);
}
2.解析init.rc脚本的部分程序
parse_config_file("/init.rc");
snprintf(tmp, sizeof(tmp), "/init.%s.rc", hardware);
parse_config_file(tmp);
==>parse_config_file
==>parse_config
==>parse_new_section
...
switch(kw) {
case K_service:
state->context = parse_service(state, nargs, args);
if (state->context) {
state->parse_line = parse_line_service;
return;
}
break;
...
==>parse_service
...
svc->name = args[1];
svc->classname = "default";//默认的classname类名
...
list_add_tail(&service_list, &svc->slist);
return svc;
3.system/init/init.c
==>main //处理restart类型的svc程序
action_for_each_trigger("early-init", action_add_queue_tail);
drain_action_queue();
action_for_each_trigger("init", action_add_queue_tail);
drain_action_queue();
action_for_each_trigger("early-boot", action_add_queue_tail);
action_for_each_trigger("boot", action_add_queue_tail);//最后执行init.rc和init.borad.rc脚本的on boot字段中的命令,其中就包括上面的class_start default命令字段
drain_action_queue();
for(;;) {
...
drain_action_queue();
restart_processes();
...
nr = poll(ufds, 3, timeout);
...
==>restart_processes
#define SVC_RESTARTING 0x08 /* waiting to restart */
#define SVC_CONSOLE 0x10 /* requires console */
==>service_for_each_flags(SVC_RESTARTING, restart_service_if_needed);
void service_for_each_flags(unsigned matchflags,
void (*func)(struct service *svc))
{
struct listnode *node;
struct service *svc;
list_for_each(node, &service_list) {//遍历service链表
svc = node_to_item(node, struct service, slist);
if (svc->flags & matchflags) {
func(svc);
}
}
}
阅读(5453) | 评论(0) | 转发(1) |