我的编程空间,编程开发者的网络收藏夹
学习永远不晚

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

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

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,     &nb sp; 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 { 
         
    struct listnode alist; 
         
    struct listnode qlist; 
         
    struct listnode tlist; 
    unsigned hash; 
    const char *name; 
    struct listnode commands; 
    struct command *current; 
}; 
struct action {
       
    struct listnode alist;
       
    struct listnode qlist;
       
    struct listnode tlist;
    unsigned hash;
    const char *name;
    struct listnode commands;
    struct command *current;
};

[cpp]

view plaincopyprint?
代码如下:
struct command 

         
    struct listnode clist; 
    int (*func)(int nargs, char **args); 
    int nargs; 
    char *args[1]; 
}; 
struct command
{
       
    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的支持在后续专题中再详细讨论。

您可能感兴趣的文章:Android init.rc文件详解及简单实例Android init.rc文件简单介绍Android miniTwitter登录界面开发实例深入剖析Android中init进程实现的C语言源码Android Init进程对信号的处理流程详细介绍


免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

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

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

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

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

Android中怎么解析XML文件

本篇文章给大家分享的是有关Android中怎么解析XML文件,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。XMLXML(eXtensible Markup Language)中
2023-05-30

Android中实现下载和解压zip文件功能代码分享

本文提供了2段Android代码,实现了从Android客户端下载ZIP文件并且实现ZIP文件的解压功能,非常实用,有需要的Android开发者可以尝试一下。 下载: DownLoaderTask.java代码如下: package com
2022-06-06

Android修改jar文件包名的方法分享

前言 jar 包我们会非常高频率的使用,尤其是用一些其他三方库的时候,往往把 java 代码打包成 jar 文件,方便项目依赖使用。 带来的问题是, 多个jar包容易出现包名冲突. 这时候我们修改 jar 文件的包名是一个比较快速有效
2022-06-06

android杂记:C++文件的添加log方法分享

这篇文章介绍了android杂记:C++文件的添加log方法,有需要的朋友可以参考一下
2022-11-15

shell替换文件中的文件路径脚本分享

用法参数1、写有需要替换路径记录的文本,格式:老路径 老名称 新路径 新名称参数2、需要替换的文件的目录参数3、需要替换的文件的类型#!/bin/sh function _replace(){basepath=$0> $basepath.l
2022-06-04

Android中使用sax解析xml文件的方法

SAX是一个解析速度快并且占用内存少的xml解析器,非常适合用于Android等移动设备。 SAX解析XML文件采用的是事件驱动,也就是说,它并不需要解析完整个文档,在按内容顺序解析文档的过程中,SAX会判断当前读到的字符是否合法XML 语
2022-06-06

Android中的类文件和类加载器实例分析

本篇内容介绍了“Android中的类文件和类加载器实例分析”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!一、Java中的类加载器首先花点时间
2023-06-30

Android中asset文件夹与raw文件夹的区别深入解析

*res/raw和assets的相同点:1.两者目录下的文件在打包后会原封不动的保存在apk包中,不会被编译成二进制。*res/raw和assets的不同点:1.res/raw中的文件会被映射到R.java文件中,访问的时候直接使用资源ID
2022-06-06

基于android中读取assets目录下a.txt文件并进行解析的深入分析

android读取assets文件下的内容,一般都是使用getAsset.open()方法,并将文件的路径作为参数传入,而当我们解析一个目录下的文件时需要对其进行解析时,比如:a.txt文件的内容为:nameandroid,liuclass
2022-06-06

android杂记:C++文件的添加log方法分享

1.添加头文件 代码如下:#include //或者 #include 这个时候可以使用ALOGE/ALOGI/ALOGW 等方法打印出log 不过有些地方不能这么使用,因为
2022-06-06

centos7中解压文件命令的示例分析

这篇文章主要介绍了centos7中解压文件命令的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。1.压缩文件夹为zip文件[root@cgls ]# zip -r my
2023-06-10

Android Beam 文件传输失败分析与解决方法

最近在修改Android7.0原生平台的一些bug,其中有关Android Beam传输文件的一些问题还是蛮多的。所以特地找时间总结下曾经踏过的坑。1.传输的文件名包含中文时,导致传输失败可能是由于Google未考虑到本地化差异,导致在传输
2023-05-30

Android应用中实现选择本地文件与目录的实例分享

文件选择器 今天给大家分享下文件选择器的作用 , 具体就是获取用户在在SD卡选中的文件/文件夹路径 ,类似于C#中OpenFileDialog控件(对C#的一站式开发还是念念不忘)。功能实现起来比较简单,主要是帮助大家节省开发时间。 网上流
2022-06-06

Android项目中解析XML文件的方法有哪些

今天就跟大家聊聊有关Android项目中解析XML文件的方法有哪些,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。1.xml文件代码
2023-05-31

Go语言中常见的文件操作分享

文件操作应该是应用程序里非常常见的一种操作,无论是哪种应用场景,几乎都离不开文件的基本操作。Go语言中提供了三个不同的包去处理文件,下午就来说说它们的具体使用
2023-01-30

编程热搜

  • Android:VolumeShaper
    VolumeShaper(支持版本改一下,minsdkversion:26,android8.0(api26)进一步学习对声音的编辑,可以让音频的声音有变化的播放 VolumeShaper.Configuration的三个参数 durati
    Android:VolumeShaper
  • Android崩溃异常捕获方法
    开发中最让人头疼的是应用突然爆炸,然后跳回到桌面。而且我们常常不知道这种状况会何时出现,在应用调试阶段还好,还可以通过调试工具的日志查看错误出现在哪里。但平时使用的时候给你闹崩溃,那你就欲哭无泪了。 那么今天主要讲一下如何去捕捉系统出现的U
    Android崩溃异常捕获方法
  • android开发教程之获取power_profile.xml文件的方法(android运行时能耗值)
    系统的设置–>电池–>使用情况中,统计的能耗的使用情况也是以power_profile.xml的value作为基础参数的1、我的手机中power_profile.xml的内容: HTC t328w代码如下:
    android开发教程之获取power_profile.xml文件的方法(android运行时能耗值)
  • Android SQLite数据库基本操作方法
    程序的最主要的功能在于对数据进行操作,通过对数据进行操作来实现某个功能。而数据库就是很重要的一个方面的,Android中内置了小巧轻便,功能却很强的一个数据库–SQLite数据库。那么就来看一下在Android程序中怎么去操作SQLite数
    Android SQLite数据库基本操作方法
  • ubuntu21.04怎么创建桌面快捷图标?ubuntu软件放到桌面的技巧
    工作的时候为了方便直接打开编辑文件,一些常用的软件或者文件我们会放在桌面,但是在ubuntu20.04下直接直接拖拽文件到桌面根本没有效果,在进入桌面后发现软件列表中的软件只能收藏到面板,无法复制到桌面使用,不知道为什么会这样,似乎并不是很
    ubuntu21.04怎么创建桌面快捷图标?ubuntu软件放到桌面的技巧
  • android获取当前手机号示例程序
    代码如下: public String getLocalNumber() { TelephonyManager tManager =
    android获取当前手机号示例程序
  • Android音视频开发(三)TextureView
    简介 TextureView与SurfaceView类似,可用于显示视频或OpenGL场景。 与SurfaceView的区别 SurfaceView不能使用变换和缩放等操作,不能叠加(Overlay)两个SurfaceView。 Textu
    Android音视频开发(三)TextureView
  • android获取屏幕高度和宽度的实现方法
    本文实例讲述了android获取屏幕高度和宽度的实现方法。分享给大家供大家参考。具体分析如下: 我们需要获取Android手机或Pad的屏幕的物理尺寸,以便于界面的设计或是其他功能的实现。下面就介绍讲一讲如何获取屏幕的物理尺寸 下面的代码即
    android获取屏幕高度和宽度的实现方法
  • Android自定义popupwindow实例代码
    先来看看效果图:一、布局
  • Android第一次实验
    一、实验原理 1.1实验目标 编程实现用户名与密码的存储与调用。 1.2实验要求 设计用户登录界面、登录成功界面、用户注册界面,用户注册时,将其用户名、密码保存到SharedPreference中,登录时输入用户名、密码,读取SharedP
    Android第一次实验

目录