本篇文章是一篇关于分析脚本文件的帖子

   

众所皆知,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 file

3. 监控系统属性变更跟事件

以下就分离依照这三点来做研讨分析.

分析和执行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作当参数. 就来从这数函开始分析

文章结束给大家分享下程序员的一些笑话语录: 很多所谓的牛人也不过如此,离开了你,微软还是微软,Google还是Google,苹果还是苹果,暴雪还是暴雪,而这些牛人离开了公司,自己什么都不是。

更多相关文章

  1. Android布局文件的属性值解析
  2. Android 文件的保存与读取之自带储存空间
  3. android读取keystore证书文件
  4. Android NFS文件系统挂载遇到的问题解决方法
  5. android小功能实现之xml文件解析(Pull)
  6. android中下载文件到sdcard和进度条小结
  7. Android R文件丢失解决办法
  8. Android init.rc文件解析过程分析

随机推荐

  1. Flex AIR应用拍照功能(Android和IOS版本)
  2. Android 图形密码
  3. Android Studio 错误 com.android.dex.De
  4. Android 获取网络时间
  5. 复选框
  6. Android 图片倒影效果源码
  7. android嵌入式底层开发
  8. 使用Android studio分析内存泄露
  9. The android SDK requaires Android Deve
  10. android调用cocos2dx例子