AndroidInitProcess分析心得(2)

來源:互聯網
上載者:User

print?//\system\core\init\init_parser.c  
int lookup_keyword(const char *s) 

    switch (*s++) { 
    case 'c': 
    if (!strcmp(s, "opy")) return K_copy; 
        if (!strcmp(s, "apability")) return K_capability; 
        if (!strcmp(s, "hdir")) return K_chdir; 
        if (!strcmp(s, "hroot")) return K_chroot; 
        if (!strcmp(s, "lass")) return K_class; 
        if (!strcmp(s, "lass_start")) return K_class_start; 
        if (!strcmp(s, "lass_stop")) return K_class_stop; 
        if (!strcmp(s, "lass_reset")) return K_class_reset; 
        //......  
    } 
    return K_UNKNOWN; 

//\system\core\init\init_parser.c
int lookup_keyword(const char *s)
{
    switch (*s++) {
    case 'c':
    if (!strcmp(s, "opy")) return K_copy;
        if (!strcmp(s, "apability")) return K_capability;
        if (!strcmp(s, "hdir")) return K_chdir;
        if (!strcmp(s, "hroot")) return K_chroot;
        if (!strcmp(s, "lass")) return K_class;
        if (!strcmp(s, "lass_start")) return K_class_start;
        if (!strcmp(s, "lass_stop")) return K_class_stop;
        if (!strcmp(s, "lass_reset")) return K_class_reset;
        //......
    }
    return K_UNKNOWN;
}
由此段程式碼可以發現此函數會根據存入的字串先由字串的第一個字元做分類, 再去比較之後的字元去回傳相對應的K_xxx.之後再將keyword傳入kw_is作判斷,Google在這裡的判斷設計kw_is會利用macro而不是用一般的函數去實作, 一是因為這個判斷動作只有單純的做比對,另外一點就是會少一次functioncall stack的效能以加快執行速度.

[cpp]
//system\core\init\init_parser.c  
#define kw_is(kw, type) (keyword_info[kw].flags & (type)) 

//system\core\init\init_parser.c
#define kw_is(kw, type) (keyword_info[kw].flags & (type))


這裡會發現是用keyword_info數組中的元素所帶出來的flags跟type作&比較.


[cpp]
//system\core\init\init_parser.c  
#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; 
} keyword_info[KEYWORD_COUNT] = { 
    [ K_UNKNOWN ] = { "unknown", 0, 0, 0 }, 
#include "keywords.h"  
}; 
 
//system\core\init\keywords.h  
//...  
    KEYWORD(capability,  OPTION,  0, 0) 
    KEYWORD(chdir,       COMMAND, 1, do_chdir) 
    KEYWORD(chroot,      COMMAND, 1, do_chroot) 
    KEYWORD(class,       OPTION,  0, 0) 
    KEYWORD(class_start, COMMAND, 1, do_class_start) 
    KEYWORD(class_stop,  COMMAND, 1, do_class_stop) 
    KEYWORD(class_reset, COMMAND, 1, do_class_reset) 
    KEYWORD(console,     OPTION,  0, 0) 
//.... 

//system\core\init\init_parser.c
#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;
} keyword_info[KEYWORD_COUNT] = {
    [ K_UNKNOWN ] = { "unknown", 0, 0, 0 },
#include "keywords.h"
};

//system\core\init\keywords.h
//...
    KEYWORD(capability,  OPTION,  0, 0)
    KEYWORD(chdir,       COMMAND, 1, do_chdir)
    KEYWORD(chroot,      COMMAND, 1, do_chroot)
    KEYWORD(class,       OPTION,  0, 0)
    KEYWORD(class_start, COMMAND, 1, do_class_start)
    KEYWORD(class_stop,  COMMAND, 1, do_class_stop)
    KEYWORD(class_reset, COMMAND, 1, do_class_reset)
    KEYWORD(console,     OPTION,  0, 0)
//....

 

由上面便可以知道keyword_info是一個Mappingtable. 每一個lookup_keyword 函數所回傳的keyword K_xxx對應一個函數do_xxx.

        因此便可以再從parse_config函數中的呼叫lookup_keyword繼續分析下去.

[cpp]
// system\core\init\init_parser.c  
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); 

// system\core\init\init_parser.c
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);
}
由之前針對lookup_keyword和kw_is的分析就可以知道, 這裡是要從init.rc中撈出keyword再利用kw_is的判斷來做不同parser方式. 由上面的程式碼可以知道, 只有在keyword_infomapping table中有SECTION flag, 才會有新的list. 而在(android4.2)目前的版本中從keywords.h所有的KEYWORD可知道, 有SECTIONflag對應到的字元只有import, on, service. 撇開import字元是用來作類似include的動作之外,on跟service就是用來建立之前所提的actionlist和service list. 接下來分析parse_new_section函數

[cpp]
//system\core\init\init_parser.c  
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; 

//system\core\init\init_parser.c
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;
}

 

由於在執行流程分析中, execute_one_command函數就只有用來執行action list上面的command,所以就從parse_action函數來分析.

[cpp]
//system\core\init\init_parser.c  
static void *parse_action(struct parse_state *state, int nargs, char **args) 

    struct action *act; 
    if (nargs < 2) { 
        parse_error(state, "actions must have a trigger\n"); 
        return 0; 
    } 
    if (nargs > 2) { 
        parse_error(state, "actions may not have extra parameters\n"); 
        return 0; 
    } 
    act = calloc(1, sizeof(*act)); 
    act->name = args[1]; 
    list_init(&act->commands); 
    list_add_tail(&action_list, &act->alist); 
        /* XXX add to hash */ 
    return act; 

//system\core\init\init_parser.c
static void *parse_action(struct parse_state *state, int nargs, char **args)
{
    struct action *act;
    if (nargs < 2) {
        parse_error(state, "actions must have a trigger\n");
        return 0;
    }
    if (nargs > 2) {
        parse_error(state, "actions may not have extra parameters\n");
        return 0;
    }
    act = calloc(1, sizeof(*act));
    act->name = args[1];
    list_init(&act->commands);
    list_add_tail(&action_list, &act->alist);
        /* XXX add to hash */
    return act;
}


由上面的程式碼可以知道, action list就是由一串act 元素所建立起來的linkedlist. 一旦action list有了新的act 元素, 接下來就執行parse_line_action函數

[cpp]
//system\core\init\init_parser.c  
static void parse_line_action(struct parse_state* state, int nargs, char **args) 

    struct command *cmd; 
    struct action *act = state->context; 
    int (*func)(int nargs, char **args); 
    int kw, n; 
 
    if (nargs == 0) { 
        return; 
    } 
 
    kw = lookup_keyword(args[0]); 
    if (!kw_is(kw, COMMAND)) { 
        parse_error(state, "invalid command '%s'\n", args[0]); 
        return; 
    } 
 
    n = kw_nargs(kw); 
    if (nargs < n) { 
        parse_error(state, "%s requires %d %s\n", args[0], n - 1, 
            n > 2 ? "arguments" : "argument"); 
        return; 
    } 
    cmd = malloc(sizeof(*cmd) + sizeof(char*) * nargs); 
    cmd->func = kw_func(kw); 
    cmd->nargs = nargs; 
    memcpy(cmd->args, args, sizeof(char*) * nargs); 
    list_add_tail(&act->commands, &cmd->clist); 

//system\core\init\init_parser.c
static void parse_line_action(struct parse_state* state, int nargs, char **args)
{
    struct command *cmd;
    struct action *act = state->context;
    int (*func)(int nargs, char **args);
    int kw, n;

    if (nargs == 0) {
        return;
    }

    kw = lookup_keyword(args[0]);
    if (!kw_is(kw, COMMAND)) {
        parse_error(state, "invalid command '%s'\n", args[0]);
        return;
    }

    n = kw_nargs(kw);
    if (nargs < n) {
        parse_error(state, "%s requires %d %s\n", args[0], n - 1,
            n > 2 ? "arguments" : "argument");
        return;
    }
    cmd = malloc(sizeof(*cmd) + sizeof(char*) * nargs);
    cmd->func = kw_func(kw);
    cmd->nargs = nargs;
    memcpy(cmd->args, args, sizeof(char*) * nargs);
    list_add_tail(&act->commands, &cmd->clist);
}


 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.