欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android中init.rc文件的解析 分享

程序员文章站 2023-11-04 14:32:28
对init.rc的解析是在parse_config(): [system/core/init/init_parser.c]中进行的。解析发生在init全过程中的哪个阶段,参...

对init.rc的解析是在parse_config(): [system/core/init/init_parser.c]中进行的。解析发生在init全过程中的哪个阶段,参看《android init进程启动过程分析》。

一、解析过程

1.      扫描init.rc中的token

    找到其中的 文件结束eof/文本text/新行newline,其中的空格‘ '、‘\t'、‘\r'会被忽略,#开头的行也被忽略掉;

    而对于text,空格‘ '、‘\t'、‘\r'、‘\n'都是text的结束标志。

2.      对每一个text token,都加入到args[]数组中

3.  当遇到新一行(‘\n')的时候,用args[0]通过lookup_keyword()检索匹配关键字;

   1) 对section(on和service),调用parse_new_section() 解析:

     - 对on section,调用parse_action(),并设置解析函数parse_line为parse_line_action()

     - 对service section,调用parse_service(),并设置解析函数parse_line为parse_line_service()

   2) 对其他关键字的行(非on或service开头的地方,也就是没有切换section)调用parse_line()

     也就是,

       - 对于on section内的命令行,调用parse_line_action()解析;

       - 对于service section内的命令行,调用parse_line_service()解析。

二、关键数据类型原型及关键数据定义

2.1 token的定义

[cpp]
#definet_eof 0  
#definet_text 1  
#definet_newline 2 

#definet_eof 0
#definet_text 1
#definet_newline 2
2.2 关键字定义

[cpp]
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(console,     option, 0, 0) 
keyword(critical,    option, 0, 0) 
keyword(disabled,    option, 0, 0) 
keyword(domainname,  command, 1, do_domainname) 
keyword(exec,        command, 1, do_exec) 
keyword(export,      command, 2, do_export) 
keyword(group,       option, 0, 0) 
keyword(hostname,    command, 1, do_hostname) 
keyword(ifup,        command, 1, do_ifup) 
keyword(insmod,      command, 1, do_insmod) 
keyword(import,      command, 1, do_import) 
keyword(keycodes,    option, 0, 0) 
keyword(mkdir,       command, 1, do_mkdir) 
keyword(mount,       command, 3, do_mount) 
keyword(on,          section, 0, 0) 
keyword(oneshot,     option, 0, 0) 
keyword(onrestart,   option, 0, 0) 
keyword(restart,     command, 1, do_restart) 
keyword(service,     section, 0, 0) 
keyword(setenv,      option, 2, 0) 
keyword(setkey,      command, 0, do_setkey) 
keyword(setprop,     command, 2, do_setprop) 
keyword(setrlimit,   command, 3, do_setrlimit) 
keyword(socket,      option, 0, 0) 
keyword(start,       command, 1, do_start) 
keyword(stop,        command, 1, do_stop) 
keyword(trigger,     command, 1, do_trigger) 
keyword(symlink,     command, 1, do_symlink) 
keyword(sysclktz,    command, 1, do_sysclktz) 
keyword(user,        option, 0, 0) 
keyword(wait,        command, 1, do_wait) 
keyword(write,       command, 2, do_write) 
keyword(copy,        command, 2, do_copy) 
keyword(chown,       command, 2, do_chown) 
keyword(chmod,       command, 2, do_chmod) 
keyword(loglevel,    command, 1, do_loglevel) 
keyword(ioprio,      option, 0, 0) 

    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(console,     option, 0, 0)
    keyword(critical,    option, 0, 0)
    keyword(disabled,    option, 0, 0)
    keyword(domainname,  command, 1, do_domainname)
    keyword(exec,        command, 1, do_exec)
    keyword(export,      command, 2, do_export)
    keyword(group,       option, 0, 0)
    keyword(hostname,    command, 1, do_hostname)
    keyword(ifup,        command, 1, do_ifup)
    keyword(insmod,      command, 1, do_insmod)
    keyword(import,      command, 1, do_import)
    keyword(keycodes,    option, 0, 0)
    keyword(mkdir,       command, 1, do_mkdir)
    keyword(mount,       command, 3, do_mount)
    keyword(on,          section, 0, 0)
    keyword(oneshot,     option, 0, 0)
    keyword(onrestart,   option, 0, 0)
    keyword(restart,     command, 1, do_restart)
    keyword(service,     section, 0, 0)
    keyword(setenv,      option, 2, 0)
    keyword(setkey,      command, 0, do_setkey)
    keyword(setprop,     command, 2, do_setprop)
    keyword(setrlimit,   command, 3, do_setrlimit)
    keyword(socket,      option, 0, 0)
    keyword(start,       command, 1, do_start)
    keyword(stop,        command, 1, do_stop)
    keyword(trigger,     command, 1, do_trigger)
    keyword(symlink,     command, 1, do_symlink)
    keyword(sysclktz,    command, 1, do_sysclktz)
    keyword(user,        option, 0, 0)
    keyword(wait,        command, 1, do_wait)
    keyword(write,       command, 2, do_write)
    keyword(copy,        command, 2, do_copy)
    keyword(chown,       command, 2, do_chown)
    keyword(chmod,       command, 2, do_chmod)
    keyword(loglevel,    command, 1, do_loglevel)
    keyword(ioprio,      option, 0, 0)
2.3 struct action 和struct command

 
[cpp]

复制代码 代码如下:

struct action { 
        /* node in list of all actions */ 
    struct listnode alist; 
        /* node in the queue of pending actions*/ 
    struct listnode qlist; 
        /* node in list of actions for atrigger */ 
    struct listnode tlist; 

    unsigned hash; 
    const char *name; 

    struct listnode commands; 
    struct command *current; 
}; 

struct action {
        /* node in list of all actions */
    struct listnode alist;
        /* node in the queue of pending actions*/
    struct listnode qlist;
        /* node in list of actions for atrigger */
    struct listnode tlist;

    unsigned hash;
    const char *name;

    struct listnode commands;
    struct command *current;
};

[cpp]

view plaincopyprint?

复制代码 代码如下:

struct command 

        /* list of commands in an action */ 
    struct listnode clist; 

    int (*func)(int nargs, char **args); 
    int nargs; 
    char *args[1]; 
}; 

struct command
{
        /* list of commands in an action */
    struct listnode clist;

    int (*func)(int nargs, char **args);
    int nargs;
    char *args[1];
};

2.4 list action_list和action_queue

action_list

    解析init.rc时,遇到on action通过act->alist加入;

    queue_builtin_action()把执行的函数组成command,创建action,挂在action_list上。

action_queue

    执行action_for_each_trigger(),通过act->qlist加入;

    queue_builtin_action()把执行的函数组成command,创建action,挂在action_list上,并追加到action_queue的队尾。

三、对action的解析

结合init的启动过程以及前面讲述的init.rc的解析,总结一下对init对init.rc里action的解析.

3.1 on section内action的解析

    1.3.1中解析到新的on section调用parse_action()时,申请了struct action *act,设置:

     1) act->name为on section的名字(比如boot/fs/);

     2) 初始化list act->commands;

     3) 把act->alist加入到action_list的列尾

    这样,action创建并加入到了action_list中。

3.2 on section内action里的command的解析

    对on section内action里的command,调用parse_line_action()

     1) 查找关键字,核对是否是command,参数数目是否正确

     2) 申请struct command *cmd

       - cmd->func从keyword表中获取;

       - 设置参数个数给cmd->nargs,拷贝参数给cmd->args;

       - 把cmd->clist加入到act->commands的列尾

    这样,command加入到了action中。

3.3 action_list里的action加入action_queue中

    action_for_each_trigger()把队列action_list里所匹配的action,追加到action_queue的队尾;

    queue_builtin_action()把执行的函数组成command,创建action,挂在action_list上,并追加到action_queue的队尾。

3.4 命令的执行

    init的无限循环中execute_one_command():system/core/init/init.c

      1) 从action_queue取下structaction *act赋给cur_action;

      2) 从cur_action获得struct command *赋给cur_command;

      3) 执行cur_command->func(cur_command->nargs, cur_command->args)

上面步骤中1, 2 & 3是一次执行的,4是无限循环执行,从action_queue上取下action,action里获得command,然后执行command。

 四、init.rc语法小结

    system/core/init/readme里有init.rc语法的描述。之前笔者没有分析init源码时,也读过这个readme文件,但是对一些概念界定都搞不太清楚。现在分析过init.rc的解析之后,下面试着对init.rc语法做一下梳理。

1.      #开头的行也被忽略掉,用于注释;

2.      ‘'、‘\t'、‘\r'都会被忽略,所以属性中含有空格的话,后面的不会被识别;每一个action里command前的缩进并无语法的要求,只是便于人阅读;

3.      ‘\n'是换行的标志,init语法里新解析的开始都是基于新行开始才进行的,是逐行扫描解析的;

4.      一些概念:section / action / command / trigger

-         init.rc里,遇到on<trigger>或service <name> <pathname> [ <argument> ]*行,标志着一个新section的开始[参看2.2里关键字定义里,类型为section的也就只有on和service];

-         遇到on <trigger>,trigger是触发条件,发生的时机。可以是early-init / init / early-fs / fs / post-fs / early-boot / boot;也可以是property:<name>=<value>,属性<name>的值被设置为<value>时;device-added-<path>/ device-removed-<path>设备节点被加入或移除时;service-exited-<name>服务退出时。

-         on <trigger>发生时,执行action,也就是on<trigger>后面的部分,可包含多个command;

-         command每条一行,支持哪些command,看2.2里关键字定义里类型为command的关键字。


形式如下:

[cpp]

on <trigger> 
    <command> 
    <command> 
    <command> 

on <trigger>
    <command>
    <command>
    <command>这整个是一个section;所有<command>叫action。

总结

本文解析了init.rc的基本语法,重点讨论on section的解析,service的解析以及property的支持在后续专题中再详细讨论。