• 函数分析AndroidInitProcess分析心得(2)


    上班之余抽点时间出来写写博文,希望对新接触的朋友有帮助。今天在这里和大家一起学习一下函数分析

    //\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的效能以快加执行速度.

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

        这里会发明是用keyword_info数组中的元素所带出来的flags跟type作&比拟.

    //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继承分析下去.

    // 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函数

        每日一道理
    这浓浓的母爱使我深深地认识到:即使你是一只矫健的雄鹰,也永远飞不出母爱的长空;即使你是一条扬帆行驶的快船,也永远驶不出母爱的长河!在人生的路上不管我们已走过多远,还要走多远,我们都要经过母亲精心营造的那座桥!
    //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函数来分析.

    //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函数

    //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);
    }

    文章结束给大家分享下程序员的一些笑话语录: 一位程序员去海边游泳,由于水性不佳,游不回岸了,于是他挥着手臂,大声求.救:“F1,F1!”

  • 相关阅读:
    010_STM32CubeMXADC
    009_STM32CubeMXPWM
    008_STM32CubeMX定时器中断
    007_STM32CubeMX外部中断
    006_STM32CubeMX按键输入
    005_STM32CubeMX串口
    004_STM32CubeMX官方例程
    003_STM32CubeMX点灯
    002_STM32CubeMX配置基础工程
    006_word发表博客到博客园中
  • 原文地址:https://www.cnblogs.com/xinyuyuanm/p/3067733.html
Copyright © 2020-2023  润新知