博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
《Android的设计与实现:卷I》——第3章 3.4.2init.rc的内容
阅读量:6548 次
发布时间:2019-06-24

本文共 3699 字,大约阅读时间需要 12 分钟。

3.4.2 init.rc的内容

熟悉了Android初始化语言,再来阅读init.rc文件就容易多了。以下是init.rc的内容:

image
image

service zygote /system/bin/app_process

-Xzygote /system/bin --zygote --start-system-server
class main
socket zygote stream 660 root system
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart media
onrestart restart netd

3.4.3 解析配置文件

我们已经熟悉了Android初始化语言和init.rc的内容。那init程序又是如何解析init.rc的呢?

解析init.rc的函数是init_parse_config_file("/init.rc"),位于/system/core/init/init_parser.c。代码如下:
int init_parse_config_file(const char fn)
{
char data;
/调用open、read,malloc读取init.rc到buffer;

并配合struct stat记录文件状态,主要记录的是文件大小,存入read_file的第二个参数保存,这里传入0,即不带回文件大小。stat结构体也是Linux定义的/data = read_file(fn, 0);if (!data) return -1;parse_config(fn, data); //开始解析init.rc/DUMP()位于/system/core/init/parser.c中,用于输出service_list和 action_list中存储的Service和Action。调试的时候作用很大,默认是关闭的/DUMP();return 0;

}

从init_parse_config_file 的函数体可以看出,它主要做了读取文件、解析文件、调试文件这三部分工作。读取文件和调试文件比较简单,都是基本的C函数。这里重点分析解析文件的部分,即parse_config(fn, data),该函数定义于init_parser.c中,代码如下:
static void parse_config(const char fn, char s)
{

struct parse_state state;        //保存当前解析状态的结构体char args[INIT_PARSER_MAXARGS];    //每行支持的最大参数个数为64int nargs;                //当前参数个数nargs = 0;state.filename = fn;            //init.rc文件路径state.line = 0;            //当前解析的行号/ptr指向当前将要解析的内容,初始时传入的是fn的文件内容,即init_parse_config_file中 的data指针。解析过程中,不断移动到将要解析的数据/state.ptr = s;  /当前解析的是什么类型的行,分为 文件结束(T_EOF)、新的一行(T_NEWLINE)、参数(T_TEXT)/ state.nexttoken = 0; /针对不同类型的行,采用不同的解析方法,初始化为 parse_line_no_op ,这是个空函数体,不做任何操作 / state.parse_line = parse_line_no_op;/在无限循环中解析init.rc,直到遇到文件结束符EOF,退出循环 /for (;;) {    /next_token函数以state为参数把每行的关键字存入args数组/    switch (next_token(&state)) {    case T_EOF: //文件结束       state.parse_line(&state, 0, 0);//传入0,表示末尾       goto parser_done;    case T_NEWLINE://新的一行       state.line++;       if (nargs) {/根据第一个关键字匹配Section/ int kw = lookup_keyword(args[0]);/如果该行是Section,即第一个关键字是on或者service/ if (kw_is(kw, SECTION)) {    /链表中最后一个元素写入0,即NULL,结束上一个Section /    state.parse_line(&state, 0, 0);     /开始新的Section解析过程/    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:
……
}

parse_config函数中主要做了两部分工作。首先提供了一个parse_state结构体存储当前解析状态,然后提供一个无限循环开始解析初始化文件。

解析过程是按行解析,并根据关键字匹配,如果遇到Section,便调用parse_new_section函数,进入Section的解析过程。parse_state定义在parser.h中,lookup_keyword和parse_new_section定义在init_parser.c中,其中lookup_keyword就是一个简单的switch语句,用来根据传入的参数匹配不同的关键字。

下面继续分析parse_new_section的内容,代码如下:

void parse_new_section(struct parse_state state, int kw, int nargs, charargs)
{

/匹配Section类型,分成Service和Action,分别对应不同的解析函数/switch(kw) {case K_service: //如果是关键字service,开始解析Service     /返回初始化的Service,由state->context引用/     state->context = parse_service(state, nargs, args);     if (state->context) {    /解析并填充Service,用真正的Service解析函数parse_line_service     代替parse_line_no_op /        state->parse_line = parse_line_service;        return;    }    break;case K_on: //如果是关键字on,即action,开始解析Action     /返回初始化的Action,由state->context引用/     state->context = parse_action(state, nargs, args);     if (state->context) {     /解析并填充Action,用真正的Action解析函数 parse_line_action      代替parse_line_no_op /        state->parse_line = parse_line_action;        return;    }    break;case K_import://如果是import语句,则重复解析初始化文件的过程    parse_import(state, nargs, args);    break;}/ 出错,未找到匹配项,复位解析函数为空函数体/state->parse_line = parse_line_no_op;

}

分析到这里,init.rc的解析过程基本明朗了。从parse_new_section函数可以看出,init.rc实际上是分成Action和Service两部分分别解析的。
解析Service调用了parse_service和parse_line_service。
解析Action调用了parse_action和parse_line_action。
接下来具体分析这4个解析函数是如何实现的。

转载地址:http://dogdo.baihongyu.com/

你可能感兴趣的文章
远离云计算风险三步走
查看>>
Silverlight 游戏开发小技巧:技能冷却效果2(Cool“.NET研究”down)2
查看>>
An Introduction to Asynchronous Programming and Twisted (2)
查看>>
vue 组件编码规范
查看>>
Java 泛型: 什么是PECS(Producer Extends, Consumer Super)
查看>>
软件包管理-打包解包压缩解压
查看>>
maven构建scala项目
查看>>
Memcached分布式缓存-windows上初步使用-网摘
查看>>
IIS无法启动的问题
查看>>
如何通过结构中的某个变量获取结构本身的指针?(container_of详解)
查看>>
Android 关于mnt/sdcard和sdcard的区别
查看>>
特征变换(7)总结
查看>>
网络工程师之路怎么走?
查看>>
go语言unix域套接字发送udp报文
查看>>
2.并发和并行
查看>>
OpenGL学习(二)用户与交互
查看>>
神奇的代码-常见错误代码注意点
查看>>
[直播一揽子]编码构思和套路
查看>>
[直播一揽子]x264参数的解释
查看>>
iOS学习之Objective-C 2.0 运行时系统编程
查看>>