您的位置:首页 > 移动开发 > Android开发

AndroidInitProcess分析心得(1)

2013-05-08 15:39 363 查看
众所皆知,Android Init process是Android启动后最先起来的进程. 真正来说Android Init process是由Linux Kernel的启动程序所驱动起来. 从device上电, Bootloader加载Kernel, 然后Kernel接着驱动Android Init process. 这一段属于Linux 的范畴, 其简单的函数呼叫流程如下:kernel_init===> init_post ==> run_init_process ==> 启动 Android Init process.由于这篇主要是分析AndroidInit process在处始化所作的工作, 因此kernel_init, init_post,run_init_process 这三个函数里的流程就不在这里作分析.Android Init process 在初始化阶段主要做三件事.1. 分析和执行init.rc脚本文件2. 创建devicenode file3. 监控系统属性变化跟事件以下就分别依照这三点来做研究分析.分析和执行init.rc脚本文件init.rc脚本文件主要是用来设定Android系统环境,还有一些待执行的进程记录.整个脚本文件可以分为两类action list跟 service list. 这两类会根据脚本文件中的关键词来作分类,1. 以"on"关键词开头的为actionlist中的元素,2. 以"Services"关键词的为servicelist中的元素.这两个关键词就跟init.rc脚本文件使用的AIL(Android Init Language)有关了.AIL 主要包含四种类型, Action, Commands, Services, Option. 这四类的语法用法在system\core\init\readme.txt中有详细描述. 这里只是简单的介绍这四类的关系, 语法用法请参考system\core\init\readme.txt.Action和Services代表着一段新的Section,所有的Section下都有Command跟Option的一些宣告.Command最主要是用来创建一些系统目录或是启动进程.Option则作为ServicesSection的一些属性设定. 比如进程是否从新被启动.分析和执行init.rc脚本文件的研究分析就由init_parse_config_file函数开始.因为此函数正是用来init.rc脚本文件作分析流程.
// \system\core\init\init_parser.cint 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;// ...state.filename = fn;state.line = 0;state.ptr = s;state.nexttoken = 0;state.parse_line = parse_line_no_op;// ...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;}}}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;}
由上面的程序代码可以很清楚的看到, 只是把init.rc脚本文件中的section中的command跟option的动作加入actionlist和service list等待执行.加入的动作可以研究parse_actionparse_service的实作.分析流程先到此, 之后再来看parse_actionparse_service的实作.以上是作init.rc脚本文件的分析流程, 而init.rc脚本文件的执行流程就由execute_one_command 函数来实作.
// \system\core\init\init.cvoid execute_one_command(void){int ret;if (!cur_action || !cur_command || is_last_command(cur_action, cur_command)) {cur_action = action_remove_queue_head();cur_command = NULL;if (!cur_action)return;INFO("processing action %p (%s)\n", cur_action, cur_action->name);cur_command = get_first_command(cur_action);} else {cur_command = get_next_command(cur_action, cur_command);}if (!cur_command)return;ret = cur_command->func(cur_command->nargs, cur_command->args);INFO("command '%s' r=%d\n", cur_command->args[0], ret);}
此函数执行到最后是利用cur_command所带的function去执行actionlist中的command. 此cur_command所带的function到底是甚么呢? 可以由前面的呼叫函数 get_first_command和 get_next_command去推导.
// \system\core\init\init.cstatic struct command *get_first_command(struct action *act){struct listnode *node;node = list_head(&act->commands);if (!node || list_empty(&act->commands))return NULL;return node_to_item(node, struct command, clist);}static struct command *get_next_command(struct action *act, struct command *cmd){struct listnode *node;node = cmd->clist.next;if (!node)return NULL;if (node == &act->commands)return NULL;return node_to_item(node, struct command, clist);}
到此我们只知道这两个函数只是从action list把actioncommand node的数据取出来, 至于这个command node所带的function还是不知道怎么来的?只好在往分析流程去找蛛丝马迹了. 在分析流程中一直执行到利用parse_config函数来做解析init.rc的动作时, 有发现在呼叫parse_new_section之前会需要先执行lookup_keyword函数去取得一个keyword当作参数. 就来从这函数开始分析
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: