热门标签 | HotTags
当前位置:  开发笔记 > Android > 正文

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

本文分析Android中如何解析init.rc文件,重点描述了onaction内的解析,并从解析的过程中总结出init.rc的语法规范。

对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或service [ ]*行,标志着一个新section的开始[参看2.2里关键字定义里,类型为SECTION的也就只有on和service];

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

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

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


形式如下:

[cpp]

on  
     
     
     

on
   
   
    这整个是一个Section;所有叫action。

总结

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


推荐阅读
  • 随着Linux操作系统的广泛使用,确保用户账户及系统安全变得尤为重要。用户密码的复杂性直接关系到系统的整体安全性。本文将详细介绍如何在CentOS服务器上自定义密码规则,以增强系统的安全性。 ... [详细]
  • 本文介绍了通过ADB命令查询Android设备CPU的当前频率、最小频率和最大频率的方法。 ... [详细]
  • 吴石访谈:腾讯安全科恩实验室如何引领物联网安全研究
    腾讯安全科恩实验室曾两次成功破解特斯拉自动驾驶系统,并远程控制汽车,展示了其在汽车安全领域的强大实力。近日,该实验室负责人吴石接受了InfoQ的专访,详细介绍了团队未来的重点方向——物联网安全。 ... [详细]
  • 本文探讨了使用普通生成函数和指数生成函数解决组合与排列问题的方法,特别是在处理特定路径计数问题时的应用。文章通过详细分析和代码实现,展示了如何高效地计算在给定条件下不相邻相同元素的排列数量。 ... [详细]
  • 在Notepad++中配置Markdown语法高亮及实时预览功能
    本文详细介绍了如何在Notepad++中配置Markdown语法高亮和实时预览功能,包括必要的插件安装和设置步骤。 ... [详细]
  • 本文提供了一种有效的方法来解决当Android Studio因电脑意外重启而导致的所有import语句出现错误的问题。通过清除缓存和重建项目结构,可以快速恢复开发环境。 ... [详细]
  • 探讨如何在映射文件中处理重复的属性字段,以避免数据操作时出现错误。 ... [详细]
  • Fiddler 安装与配置指南
    本文详细介绍了Fiddler的安装步骤及配置方法,旨在帮助用户顺利抓取用户Token。文章还涵盖了一些常见问题的解决方案,以确保安装过程顺利。 ... [详细]
  • 网络流24题——试题库问题
    题目描述:假设一个试题库中有n道试题。每道试题都标明了所属类别。同一道题可能有多个类别属性。现要从题库中抽取m道题组成试卷。并要求试卷包含指定类型的试题。试设计一个满足要求的组卷算 ... [详细]
  • Android 中的布局方式之线性布局
    nsitionalENhttp:www.w3.orgTRxhtml1DTDxhtml1-transitional.dtd ... [详细]
  • 利用无代码平台实现高效业务应用开发
    随着市场环境的变化加速,全球企业都在探索更为敏捷的应用开发模式,以便快速响应新兴的商业机遇。然而,传统的软件开发方式不仅成本高昂,而且耗时较长,这往往导致IT与业务部门之间的合作障碍,进而影响项目的成功。本文将探讨如何通过无代码开发平台解决这些问题。 ... [详细]
  • 在Android应用开发过程中,开发者经常遇到诸如CPU使用率过高、内存泄漏等问题。本文将介绍几种常用的命令及其应用场景,帮助开发者有效定位并解决问题。 ... [详细]
  • 为何Compose与Swarm之后仍有Kubernetes的诞生?
    探讨在已有Compose和Swarm的情况下,Kubernetes是如何以其独特的设计理念和技术优势脱颖而出,成为容器编排领域的领航者。 ... [详细]
  • 本文介绍了如何通过安装 sqlacodegen 和 pymysql 来根据现有的 MySQL 数据库自动生成 ORM 的模型文件(model.py)。此方法适用于需要快速搭建项目模型层的情况。 ... [详细]
  • 处理Android EditText中数字输入与parseInt方法
    本文探讨了如何在Android应用中从EditText组件安全地获取并解析用户输入的数字,特别是用于设置端口号的情况。通过示例代码和异常处理策略,展示了有效的方法来避免因非法输入导致的应用崩溃。 ... [详细]
author-avatar
16_阿PIE覀_295
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有