android源码版本-->4.4.2
linux源码版本-->3.4
一. 总体分析
init_parse_config_file("/init.rc");
二.代码分析
在system/core/init/init.c中
-
int init_parse_config_file(const char *fn)
-
{
-
char *data;
-
//将"/init.rc"的内容全部读取到以data为首指针的buffer中,函数会调用malloc(sz+2)
-
//多分配的两个字体是结束标志,会在文件最后添加结束标志\n\0
-
data = read_file(fn, 0);
-
if (!data) return -1;
-
-
parse_config(fn, data);
-
DUMP();
-
return 0;
-
}
在system/core/init/init_parser.c中
-
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)) { //对service on import这三类进行处理
-
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; //如果是text则放到字符串数组中,直到section结束
-
INFO("text=%s", state.text); //做为section的参数
-
}
-
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);
-
}
-
}
下面以为例说明一下对rc脚本的解析
-
# virtual sdcard daemon running as media_rw (1023)
-
service sdcard /system/bin/sdcard -u 1023 -g 1023 -l /data/media /mnt/shell/emulated
-
class late_start
第1步: next_token会顺序搜索service这一行,并按空格依次分隔每个字段
-
args[0]=service
-
args[1]=sdcard
-
args[2]=/system/bin/sdcard
-
args[3]=-u
-
args[4]=1023
-
args[5]=-g
-
args[6]=1023
-
args[7]=-l
-
args[8]=/data/media
-
args[9]=/mnt/shell/emulated
-
最后nargs=9,完成之后遇到\n换行符就到了case
执行完后nargs=9,此行解析完成后遇到\n换行符,case T_NEWLINE
第2步:进入parse_new_section
-
void parse_new_section(struct parse_state *state, int kw,
-
int nargs, char **args)
-
{
-
switch(kw) {
-
case K_service: //因为本实例的关键字是service,所以进入parse_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;
-
}
第3步:进入parse_service-->构造struct service并放到链表中
-
static void *parse_service(struct parse_state *state, int nargs, char **args)
-
{
-
struct service *svc;
-
//检查参数的个数: 最小的例子:service sdcard /system/bin/sdcard,所以最小是3个
-
if (nargs < 3) {
-
parse_error(state, "services must have a name and a program\n");
-
return 0;
-
}
-
//检查service_name是否合法:长度不能大于16,不能含有除字母 数字 _ - 之外的字符
-
if (!valid_name(args[1])) {
-
parse_error(state, "invalid service name '%s'\n", args[1]);
-
return 0;
-
}
-
//如果在service链表中找到了,说明有重名的service,这也不合法
-
svc = service_find_by_name(args[1]);
-
if (svc) {
-
parse_error(state, "ignored duplicate definition of service '%s'\n", args[1]);
-
return 0;
-
}
-
//最后构造struct service,放到链表中
-
nargs -= 2;
-
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;
-
svc->onrestart.name = "onrestart";
-
list_init(&svc->onrestart.commands);
-
list_add_tail(&service_list, &svc->slist);
-
return svc;
-
}
第4步: 设置flags
-
static void parse_line_service(struct parse_state *state, int nargs, char **args)
-
{
-
svc->ioprio_class = IoSchedClass_NONE;
-
kw = lookup_keyword(args[0]);
-
switch (kw) {
-
case K_capability:
-
break;
-
case K_class:
-
if (nargs != 2) {
-
parse_error(state, "class option requires a classname\n");
-
} else {
-
svc->classname = args[1];
-
}
-
break;
-
......
-
case K_oneshot:
-
svc->flags |= SVC_ONESHOT; //只是改了标志位而己
-
break;
-
....
-
default:
-
parse_error(state, "invalid option '%s'\n", args[0]);
-
}
-
}
阅读(1274) | 评论(0) | 转发(0) |