Android中init.rc文件的解析 分享
Android中init.rc文件的解析 分享
发布时间:2016-12-28 来源:查字典编辑
摘要:对init.rc的解析是在parse_config():[system/core/init/init_parser.c]中进行的。解析发生在...

对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的支持在后续专题中再详细讨论。

推荐文章
猜你喜欢
附近的人在看
推荐阅读
拓展阅读
相关阅读
网友关注
最新安卓软件开发学习
热门安卓软件开发学习
编程开发子分类