Chinaunix首页 | 论坛 | 博客
  • 博客访问: 15531398
  • 博文数量: 2005
  • 博客积分: 11986
  • 博客等级: 上将
  • 技术积分: 22535
  • 用 户 组: 普通用户
  • 注册时间: 2007-05-17 13:56
文章分类

全部博文(2005)

文章存档

2014年(2)

2013年(2)

2012年(16)

2011年(66)

2010年(368)

2009年(743)

2008年(491)

2007年(317)

分类: LINUX

2009-01-05 16:53:04

浅析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);
        }
    }
}

阅读(5474) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~