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

(0)

相关推荐

  • Android miniTwitter登录界面开发实例

    本文要演示的Android开发实例是如何完成一个Android中的miniTwitter登录界面,下面将分步骤讲解怎样实现图中的界面效果,让大家都能轻松的做出美观的登录界面. 先贴上最终要完成的效果图: miniTwitter登录界面的布局分析 首先由界面图分析布局,基本可以分为三个部分,下面分别讲解每个部分. 第一部分是一个带渐变色背景的LinearLayout布局,关于背景渐变色就不再贴代码了,效果如下图所示: 第二部分,红色线区域内,包括1,2,3,4 如图所示: 红色的1表示的是一个带圆

  • 深入剖析Android中init进程实现的C语言源码

    概述 init是一个进程,确切的说,它是Linux系统中用户空间的第一个进程.由于Android是基于Linux内核的,所以init也是Android系统中用户空间的第一个进程.init的进程号是1.作为天字第一号进程,init有很多重要的工作: init提供property service(属性服务)来管理Android系统的属性. init负责创建系统中的关键进程,包括zygote. 以往的文章一上来就介绍init的源码,但是我这里先从这两个主要工作开始.搞清楚这两个主要工作是如何实现的,我

  • Android init.rc文件简单介绍

    Android init.rc文件简单介绍 init.rc脚本是由Android中linux的第一个用户级进程init进行解析的. init.rc 文件并不是普通的配置文件,而是由一种被称为"Android初始化语言"(Android Init Language,这里简称为AIL)的脚本写成的文件. 该文件在ROM中是只读的,即使有了root权限,可以修改该文件也没有.因为我们在根目录看到的文件只是内存文件的镜像.也就是说,android启动后,会将init.rc文件装载到内存.而修改

  • Android Init进程对信号的处理流程详细介绍

    Android  Init进程对信号的处理流程 在Android中,当一个进程退出(exit())时,会向它的父进程发送一个SIGCHLD信号.父进程收到该信号后,会释放分配给该子进程的系统资源:并且父进程需要调用wait()或waitpid()等待子进程结束.如果父进程没有做这种处理,且父进程初始化时也没有调用signal(SIGCHLD, SIG_IGN)来显示忽略对SIGCHLD的处理,这时子进程将一直保持当前的退出状态,不会完全退出.这样的子进程不能被调度,所做的只是在进程列表中占据一个

  • Android init.rc文件详解及简单实例

    Android init.rc文件详解 本文主要来自$ANDROID_SOURCE/system/init/readme.txt的翻译. 1 简述 Android init.rc文件由系统第一个启动的init程序解析,此文件由语句组成,主要包含了四种类型的语句:Action,Commands,Services,Options.在init.rc文件中一条语句通常是占据一行.单词之间是通过空格符来相隔的.如果需要在单词内使用空格,那么得使用转义字符"\",如果在一行的末尾有一个反斜杠,那么

  • Android中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的结束标志.

  • Android中对xml文件解析的3种方式总结

    前言 xml 是数据传输的一种格式,Android 中的布局文件.设置文件等都采用它来表示.Android 中对 xml 文件的解析也有多种方式,下面介绍常用的 3 种方式: Dom . SAX 和 dom4j.下面话不多说了,来一起看看详细的介绍吧. 先看一个简单的 xml 文件: <?xml version="1.0" encoding="UTF-8" standalone="no"?> <书 出版社="骏马&qu

  • Android 中build.prop 文件与 getprop 命令

    Android 中build.prop 文件与 getprop 命令 在android系统中,它的根文件系统下有几个用于启动系统时需要的配置文件: /init.rc /default.prop /system/build.prop 我们先看看 build.prop 里面到底有些什么东西: E:\AndroidProject\NowaMagic>adb shell shell@android:/ $ su su root@android:/ # cd system cd system root@a

  • Android开发实现Files文件读取解析功能示例

    本文实例讲述了Android开发实现Files文件读取解析功能.分享给大家供大家参考,具体如下: package com.example.file; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.Button; import android.widg

  • Android 中读取Excel文件实例详解

    Android 中读取Excel文件实例详解 最近有个需求需要在app内置数据,新来的产品扔给了我两个Excel表格就不管了(两个表格格式还不统一...),于是通过度娘等方法找到了Android中读取Excel表格文件的一种方法,记录一下. 闲话一下Excel中工作簿和工作表的区别: 工作簿中包含有工作表.工作簿可以由一张或多张工作表组成,一个工作簿就是一个EXCEL表格文件. 好了,开始读取表格文件吧. 前提 首先,我们假设需要读取的表格文件名字为test.xls, 位于assets根目录下.

  • Android 中Manifest.xml文件详解

    Android 中Manifest.xml文件详解 每一个Android项目都包含一个清单(Manifest)文件--AndroidManifest.xml,它存储在项目层次中的最底层.清单可以定义应用程序及其组件的结构和元数据. 它包含了组成应用程序的每一个组件(活动.服务.内容提供器和广播接收器)的节点,并使用Intent过滤器和权限来确定这些组件之间以及这些组件和其他应用程序是如何交互的. 它还提供了各种属性来详细地说明应用程序的元数据(如它的图标或者主题)以及额外的可用来进行安全设置和单

  • Android 中的类文件和类加载器详情

    目录 一.Java中的类加载器 二.Android中的类加载器 2.1 BootClassLoader 2.2 PathClassLoader 2.3 DexClassLoader 2.4 InMemoryDexClassLoader 三.Dex文件 3.1 Android内存中的Dex文件 3.2 Dex文件的生成 一.Java中的类加载器 首先花点时间回顾一下Java中的三种类加载器: BootStrap ClassLoader 启动类加载器,它是实现自C/C++的类加载器,用于加载JDK的

  • 简述Android中实现APP文本内容的分享发送与接收方法

    谨记(指定选择器Intent.createChooser()) 开始今天的内容前,先闲聊一下: (1)突然有一天头脑风暴,对很多问题有了新的看法和见解,迫不及待的想要分享给大家,文档已经写好了,我需要通过微信或者QQ,短信等社交工具发送给大家. (2)在网上发现一段特别好的文章,想要保存收藏下来. 上面描述了进入智能手机时代后,我们经常遇到的两种情况,那么作为开发者的我们如何让自己开发的APP实现这两种功能呢,下面我们以实现文本的发送分享以及接收来梳理下两种功能的实现过程(其他类型的数据在博文末

随机推荐