浅析kernel启动的第1个用户进程init如何解读init.rc脚本

来源:互联网 发布:平板上淘宝直播怎么看 编辑:程序博客网 时间:2024/05/10 15:15

浅析kernel启动的第1个用户进程init如何解读init.rc脚本

首先解读
1.on init字段到来,state->context为新申请到的struct action结构体,并将其挂接到action_list尾部,然后初始化处理方法,
之后该section内的所有command都将挂接到act->commands链表上,这样也就有了立体层次[luther.gliethttp].
state->parse_line = parse_line_action;这样以后的"行脚本"将使用这个方法来做处理.
2.loglevel 3因为为cmd,
所以会将动态malloc一个struct command缓冲区,
    cmd = malloc(sizeof(*cmd) + sizeof(char*) * nargs);
    cmd->func = kw_func(kw);
    cmd->nargs = nargs;
    memcpy(cmd->args, args, sizeof(char*) * nargs);
    list_add_tail(&act->commands, &cmd->clist);//先将cmd结构体放到list链表尾,后面会集中处理.
3.之后就都是上面的重复工作了.

一个on和一个service都将创建一个新的struct action结构体,之后作为当前state->context来处理接下来的所有cmd,
所以接下来的所有cmd也就都将挂接到这个新的act->commands链表上,感觉这样一来脚本非常有层次感,管理起来也很舒服.
4.对于service服务段处理,如果为service命令,那么,先检查service_list链表上是否已经有了同名的服务[luther.gliethttp].
    svc = service_find_by_name(args[1]);
    if (svc) {
        parse_error(state, "ignored duplicate definition of service '%s'/n", args[1]);
        return 0;
    }
    svc = calloc(1, sizeof(*svc) + sizeof(char*) * nargs);
    if (!svc) {
        parse_error(state, "out of memory/n");
        return 0;
    }
    svc->name = args[1];
    svc->classname = "default";
    memcpy(svc->args, args + 2, sizeof(char*) * nargs);
    svc->args[nargs] = 0;
    svc->nargs = nargs;
    list_add_tail(&service_list, &svc->slist);//将这个service控制结构体添加到service_list链表尾.
然后将paser的方法指向service方法
    state->parse_line = parse_line_service;//以下所有参数都将使用parse_line_service进行解析.
5.service命令后边的参数都将用来改变该service控制结构体里的项,不同的service命令,
对args有不同的解析方式,都在parse_line_service中完成,比如:
1 service dund /system/bin/dund /
2 --listen --channel=5 --nodetach --pppd=/system/bin/pppd /
3 192.168.0.100:192.168.0.101 nodefaultroute unit 1 linkname bluetooth
4 user bluetooth
5 group bluetooth net_bt_admin
6 disabled
那么1行开始将申请一个service结构体,然后挂接到service_list链表上,
之后的5行都是用来控制这个service结构体里边的数据项,直到在行首遇到下一个service关键字或者on才会停止[luther.gliethttp].

好了,基本的命令字和立体的脚本解析结构,已经说完了,那么从init.rc脚本解析出来的咚咚在啥时候用呢,

1.对于on节提供的对外接口
void action_for_each_trigger(const char *trigger,
                             void (*func)(struct action *act))
void queue_property_triggers(const char *name, const char *value)
void queue_all_property_triggers()
举个例子
    action_for_each_trigger("early-init", action_add_queue_tail);
    action_for_each_trigger("init", action_add_queue_tail);
    action_for_each_trigger("early-boot", action_add_queue_tail);
    action_for_each_trigger("boot", action_add_queue_tail);
2.对于service节提供的对外接口
struct service *service_find_by_name(const char *name)
struct service *service_find_by_pid(pid_t pid)
void service_for_each_class(const char *classname,
                            void (*func)(struct service *svc))
void service_for_each_flags(unsigned matchflags,
                            void (*func)(struct service *svc))
举个例子
int do_start(int nargs, char **args)
{
    struct service *svc;
    svc = service_find_by_name(args[1]);
    if (svc) {
        service_start(svc);
    }
    return 0;
}