工具:Source Insight

最好也打开源码,一步一步的跟,并仔细看后面的注释。


一、linux内核起来后,android的第一个用户进程:init
1.那么来看看init.c中的main函数,它做了什么?
Init.csystem\core\Init打开source Insigt
可以看到:
...
open_devnull_stdio();
log_init();
INFO("reading config file\n");
parse_config_file("/init.rc");
...
2. 现在主要分析:parse_config_file("/init.rc");这个函数
跟进去:int parse_config_file(const char *fn)
{
char *data;
data = read_file(fn, 0);/*读取配置文件内容,这个文件就是init.c*/
if (!data) return -1;

parse_config(fn, data);/*调用parse_config做真正的解析*/
DUMP();
return 0;
}
3.看parse_config到底什么解析:
state.parse_line = parse_line_no_op; /*设置解析函数,
for (;;) { 不同的内容用不同的解析函数*/
switch (next_token(&state)) {
case T_EOF:
state.parse_line(&state, 0, 0);
return;
case T_NEWLINE:
if (nargs) {
int kw = lookup_keyword(args[0]);
if (kw_is(kw, SECTION)) { /*判断关键字类型是不是SECTION*/
state.parse_line(&state, 0, 0);
parse_new_section(&state, kw, nargs, args); /*是的话解析新的SECTION*/
} else {
state.parse_line(&state, nargs, args);
}
nargs = 0;
}
break;
case T_TEXT:
if (nargs < SVC_MAXARGS) {
args[nargs++] = state.text;
}
break;
}
}
可见,这个函数是以一个一个Section进行解析的,而且不同的section使用不同的解析函数。
4. 那么,如何判断那些属于一个section呢?
1) 先去看看keyword.h中:
#ifndef KEYWORD
int do_class_start(int nargs, char **args); /*声明一些函数,不同的内容用不同的解析函数*/
int do_class_stop(int nargs, char **args);
...
...
#define __MAKE_KEYWORD_ENUM__
#define KEYWORD(symbol, flags, nargs, func) K_##symbol, /*定义KEYWORD宏,虽然有四个参数,但这里只用一个 (得到K_symbol)*/
enum { /*定义了各个关键字的枚举值*/
#endif
KEYWORD(capability, OPTION, 0, 0) /*宏展开为:K_capability*/
KEYWORD(class, OPTION, 0, 0)
KEYWORD(class_start, COMMAND, 1, do_class_start)
....
....
#ifdef __MAKE_KEYWORD_ENUM__
KEYWORD_COUNT,
};
#undef __MAKE_KEYWORD_ENUM__
#undef KEYWORD /*取消宏定义*/
#endif


2) 再看看,parser.c中:
/*第一次包含*/ #include "keywords.h" /*第一次包含得到了一个枚举定义。*/
/*接下来重新定义KEYWORD宏,*/
#define KEYWORD(symbol, flags, nargs, func) \
[ K_##symbol ] = { #symbol, func, nargs + 1, flags, },


struct {
const char *name; /*关键字的名称*/
int (*func)(int nargs, char **args);/*对应关键字的处理函数*/
unsigned char nargs; /*参数个数,每个关键字的参数个数是固定的*/
unsigned char flags; /*关键字的属性有三种:COMMEND,OPTION,SECTION,
其中COMMAND有对应的处理函数*/
} keyword_info[KEYWORD_COUNT] = {
[ K_UNKNOWN ] = { "unknown", 0, 0, 0 },
/*第二次包含*/ #include "keywords.h"

};


#undef KEYWORD

#define kw_is(kw, type) (keyword_info[kw].flags & (type))
#define kw_name(kw) (keyword_info[kw].name)
#define kw_func(kw) (keyword_info[kw].func)
#define kw_nargs(kw) (keyword_info[kw].nargs)
从中可以发现,包含了两次头文件,第一次包含得到了一个枚举定义。

将#include "keywords.h"替换,就可以很清楚的知道什么回事了:
第一步为:(也就是第一次#include "keywords.h"之前)
KEYWORD(capability, OPTION, 0, 0) /*宏展开为:K_capability*/
KEYWORD(class, OPTION, 0, 0)
KEYWORD(class_start, COMMAND, 1, do_class_start)
KEYWORD(class_stop, COMMAND, 1, do_class_stop)
......
第二步:第一次替换成: (第一次#include "keywords.h"之后)
K_capability
K_class
K_class_start
K_class_stop

第三步:重新定义KEYWORD
#define KEYWORD(symbol, flags, nargs, func) \
[ K_##symbol ] = { #symbol, func, nargs + 1, flags, },
第四步:第二次#include "keywords.h"
struct {
const char *name; /*关键字的名称*/
int (*func)(int nargs, char **args);/*对应关键字的处理函数*/
unsigned char nargs; /*参数个数,每个关键字的参数个数是固定的*/
unsigned char flags; /*关键字的属性有三种:COMMEND,OPTION,SECTION,
其中COMMAND有对应的处理函数*/
} keyword_info[KEYWORD_COUNT] = {
[ K_UNKNOWN ] = { "unknown", 0, 0, 0 },

[K_capability] = "capability",func,nargs+1,flags,},
[K_class] = "class",func,nargs+1,flags,},
.....
};

回到第四点的问题:我们在keywords.h中发现只有
KEYWORD(on, SECTION, 0, 0)
KEYWORD(service, SECTION, 0, 0)
这两的中含有关键字SECTION。

5.我们进init.rc中

on init #on 关键字标志一个section,对应的名字为“init”
# 下面所有的内容都属于这个section,直到下一个section开始时
sysclktz 0

loglevel 3

# setup the global environment
export PATH /sbin:/system/sbin:/system/bin:/system/xbin
export LD_LIBRARY_PATH /system/lib
export ANDROID_BOOTLOGO 1 #根据keyword.h可知,export表示一个command
export ANDROID_ROOT /system
export ANDROID_ASSETS /system/app
export ANDROID_DATA /data
....
....
on boot
...
...
class_start default

#class_start也是一个command,对应函数为do_class_start
#keywords.h--->KEYWORD(class_start, COMMAND, 1, do_class_start)
...
...
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
socket zygote stream 666
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart media

6. 解析service
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
socket zygote stream 666 #socket是OPTION
#下面的onrestart是OPTION,而write和restart是COMMAND。
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart media
解析section的入口函数是parser.c---->parse_new_section(&state, kw, nargs, args);
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;
}
state->parse_line = parse_line_no_op;
}

更多相关文章

  1. Android(安卓)xUtils3源码解析之注解模块
  2. Android(安卓)浏览器插件开发-插件库
  3. Android(安卓)ApiDemos示例解析(154):Views->Layouts->ScrollVie
  4. Android6.0 按键流程(三)InputDispatcher分发输入消息
  5. Android(安卓)Volley 源码解析
  6. Android自定义数字键盘解析
  7. Android(安卓)学习资料
  8. android中利用GPS获取位置信息的源码分析
  9. 解析xml

随机推荐

  1. Android(安卓)在java代码中使用selector
  2. Android操作SQLite数据库(增、删、改、查
  3. 学员_国培阶段性学习总结
  4. VisionMobile: 开放管控指数(三) -- 开源管
  5. android app 开发过程中 对于性能优化的
  6. 【Activity&Task&Stack】Android 中 Acti
  7. 实例+详解剖析Android之自定义View
  8. 最近学习Android的一些体会
  9. 利用Android SDK免root权限抓屏
  10. 八款常见的Android游戏引擎