Android Init进程解析init.rc

匿名 (未验证) 提交于 2019-12-03 00:34:01

主要是通过该函数实现解析:在init.c中

init_parse_config_file("/init.rc");
int init_parse_config_file(const char *fn) {     char *data;     //读取文件的内容     data = read_file(fn, 0);     if (!data) return -1;     //真正解析的函数     parse_config(fn, data);     DUMP();     return 0; }
static void parse_config(const char *fn, char *s) {     struct parse_state state;     struct listnode import_list;     struct listnode *node;     char *args[INIT_PARSER_MAXARGS];     int nargs;      nargs = 0;     state.filename = fn;     state.line = 0;     state.ptr = s;     state.nexttoken = 0;     state.parse_line = parse_line_no_op;      list_init(&import_list);     state.priv = &import_list;      for (;;) {         switch (next_token(&state)) {         case T_EOF:             state.parse_line(&state, 0, 0);             goto parser_done;         case T_NEWLINE:             state.line++;             if (nargs) {                 int kw = lookup_keyword(args[0]);                 if (kw_is(kw, SECTION)) {                     state.parse_line(&state, 0, 0);                     parse_new_section(&state, kw, nargs, args);                 } else {                     state.parse_line(&state, nargs, args);                 }                 nargs = 0;             }             break;         case T_TEXT:             if (nargs < INIT_PARSER_MAXARGS) {                 args[nargs++] = state.text;             }             break;         }     }  parser_done:     list_for_each(node, &import_list) {          struct import *import = node_to_item(node, struct import, list);          int ret;           INFO("importing '%s'", import->filename);          ret = init_parse_config_file(import->filename);          if (ret)              ERROR("could not import file '%s' from '%s'\n",                    import->filename, fn);     } }

#include "keywords.h"  #define KEYWORD(symbol, flags, nargs, func) \     [ K_##symbol ] = { #symbol, func, nargs + 1, flags, },  static struct {     const char *name;     int (*func)(int nargs, char **args);     unsigned char nargs;     unsigned char flags; } keyword_info[KEYWORD_COUNT] = {     [ K_UNKNOWN ] = { "unknown", 0, 0, 0 }, #include "keywords.h" }; #undef KEYWORD

在keywords.h中,将关键字分成了三类,分别是:Section、Command、Option.以init.rc中的一段来看parser_config函数是如何解析的。其中三个关键字被分类为Section:import,on,service

service servicemanager /system/bin/servicemanager     class core     user system     group system     critical     onrestart restart healthd     onrestart restart zygote     onrestart restart media     onrestart restart surfaceflinger     onrestart restart drm

第一次执行next_token()出来,case t_text,此时,nargs = 1, args[0] = service

第二次执行next_token()出来,case t_text,此时, nargs =2, args[0] = service, args[1] = servicemanager,

parse_new_section

static void parse_new_section(struct parse_state *state, int kw,                        int nargs, char **args) {     printf("[ %s %s ]\n", args[0],            nargs > 1 ? args[1] : "");     switch(kw) {     case K_service:         state->context = parse_service(state, nargs, args);         if (state->context) {             state->parse_line = parse_line_service;             return;         }         break;     case K_on:         state->context = parse_action(state, nargs, args);         if (state->context) {             state->parse_line = parse_line_action;             return;         }         break;     case K_import:         parse_import(state, nargs, args);         break;     }     state->parse_line = parse_line_no_op; }

对于service和action,其实就是实例化一个service和action的结构体,添加到service的list和action的list里面去,并且将parse_line函数转换成对应的prase_line_action/service函数;对于import,则是将import的路径,以及import的文件名保存到import的list里面去。

对于service,parse_new_section的主要做了两件事:1、实例化一个service添加到service的list中;2、将prase_line函数赋值成prase_line_service.

对于class这种属于Option分类的,是用来补充service的信息的。

 case K_class:         if (nargs != 2) {             parse_error(state, "class option requires a classname\n");         } else {             svc->classname = args[1];         }         break;

对于onrestart是属于Option分类,后面接的是Command,用来表示重启要做什么动作。

   case K_onrestart:         nargs--;         args++;         //kw是restart         kw = lookup_keyword(args[0]);         if (!kw_is(kw, COMMAND)) {             parse_error(state, "invalid command '%s'\n", args[0]);             break;         }         kw_nargs = kw_nargs(kw);         if (nargs < kw_nargs) {             parse_error(state, "%s requires %d %s\n", args[0], kw_nargs - 1,                 kw_nargs > 2 ? "arguments" : "argument");             break;         }          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(&svc->onrestart.commands, &cmd->clist);         break;

service有一个Command的list,专门用来保存onrestart要做的操作。

对于Action和Service类型的Section,其解析的流程都是类似的,解析的过程就是讲init.rc中的配置,映射到c++中的对象。

对于import类型的Section,其解析的流程就是将import文件的路径和文件名,保存到import_list

static void parse_import(struct parse_state *state, int nargs, char **args) {     struct listnode *import_list = state->priv;     struct import *import;     char conf_file[PATH_MAX];     int ret;      if (nargs != 2) {         ERROR("single argument needed for import\n");         return;     }     //展开属性,对于变量(即通过$引用的,找到它实际的值,替换进去,保存对应的路径)     ret = expand_props(conf_file, args[1], sizeof(conf_file));     if (ret) {         ERROR("error while handling import on line '%d' in '%s'\n",               state->line, state->filename);         return;     }      import = calloc(1, sizeof(struct import));     import->filename = strdup(conf_file);     list_add_tail(import_list, &import->list);     INFO("found import '%s', adding to import list", import->filename); }

本文件解析完成之后,再对import的文件进行同样的解析。

parser_done:     list_for_each(node, &import_list) {          struct import *import = node_to_item(node, struct import, list);          int ret;           INFO("importing '%s'", import->filename);          ret = init_parse_config_file(import->filename);          if (ret)              ERROR("could not import file '%s' from '%s'\n",                    import->filename, fn);     } }




标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!