Android init.rc文件详解

2024-08-31 00:18
文章标签 android init rc 详解

本文主要是介绍Android init.rc文件详解,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

首先,个人为了很好的总结这方面的知识体系,以下绝大多数内容都是博主从网上那些大神多方面摘抄过来的。

一、文件简介

init.rc:Android在启动过程中读取的启动脚本文件,主要完成一些初级的初始化,在/system/core/init/init.c中解析。rc 经常被用作程序之启动脚本的文件名。它是“run commands”(运行命令)的缩写。

init.xx.rc:与具体CPU相关的启动脚本,比如对于MTK的CPU,名字为init.usb.rc,init.trace.rc。在init.rc之后得到解析。

对于运行的设备,两个文件都位于根目录下:autochips\device\atc\ac8317\configs
对于编译后的源码,位于out\target\product\ac8317\root

二、init.rc和init.xx.rc文件的修改

我们以 init.rc 来入手,学习 rc 的用法。
\autochips\device\atc\ac8317\configs\init_for_mmc.rc
system/core/init.c

文件结构
init.rc 基本单位是 section。
section 有三种类型:
1. on
2. service
3. import
如果想对这方面作个更加详细的理解的朋友请移步至Android init.rc文件浅析 阅读

on 类型
on 类型 表示一系列的命令组合,eg:

on initmkdir /productinfo 0771 system system# SPRD: modify for storage manage @{mount tmpfs tmpfs /storage mode=0751,gid=1028# @}mkdir /mnt/media_rw/sdcard0 0700 media_rw media_rwmkdir /storage/sdcard0 0700 root rootmkdir /mnt/shell/emulated 0700 shell shellmkdir /storage/emulated 0555 root root# SPRD: move this to board level init @{#export EXTERNAL_STORAGE /storage/emulated/legacy#export SECONDARY_STORAGE /storage/sdcard0# @}# SPRD: for storage manage @{export LEGACY_STORAGE /storage/emulated/legacy# @}

这样一个 section 里面包含了多个命令。命令的执行是以 section 为单位的。
上面这些命令都会一起顺序执行,不会单独执行。
他们的执行由 init.c 的 main() 决定。在当其中调用

init.c文件:

action_for_each_trigger("early-init", action_add_queue_tail);

时,就将 on init 开始的这样一个 section 里所有的命令加入到一个执行队列,在未来某个时候会顺序执行队列里的命令。

该方法在init_parser.c文件中实现:

void action_for_each_trigger(const char *trigger,void (*func)(struct action *act))
{struct listnode *node;struct action *act;list_for_each(node, &action_list) {act = node_to_item(node, struct action, alist);if (!strcmp(act->name, trigger)) {func(act);}}
}

这里写图片描述

service 类型
service 类型 的section 表示一个可执行的程序,下面是个人工作内容中片段代码:

例一:

service gocsdk /system/bin/gocsdkclass maindisabledoneshoton property:sys.boot_completed=1chmod 777 /dev/goc_serialstart gocsdk

gocsdk 作为一个名字标识了这个 service,这个可执行程序的位置在 /system/bin/gocsdk。
下面的 disable、oneshot 被称为 options,options 是用来描述的 service 的特点,不同的 service 有不同的 options。

service 的执行时间是在property:sys.boot_completed=1 这个命令被执行的时候,这个命令总存在于某个 on 类型的section 中作为一个服务启动的动作(Action)。

就拿上面的代码来说property:sys.boot_completed=1满足条件被执行时,则会启动这个类型为 main的 gocsdk service。

例二:

service yo_service1 /system/bin/yo_service1class coreuser systemdisabledgroup system radio shelloneshoton yo_fsclass_start core

其中 yo_service1 这个 service 的类型是 core。
在 yo_fs 被调用的时候则将会 class_start 而执行所有 类型为 core 的 service。

import 类型
import 类型表示包含了另外一些 section,在解析完 init.rc 后会继续调用 init_parse_config_file 来解析引入的 .rc 文件。
eg:
比如我们在 init.sc8830.rc 的开始可以看到

import /init.usb.rc
import /init.trace.rc

表示在运行完本 rc 后还将继续运行 init.usb.rc 和 init.trace.rc。

init.rc 文件解析过程
解析 init.rc 的过程就是识别一个个 section 的过程。
在 init.c 中的 main() 中去执行一个个命令。
(android采用双向链表来存储section的信息,解析完成之后,会得到三个双向链表action_list、service_list、import_list来分别存储三种section的信息上。)

system/core/init/init.c
在 init.c 中调用

init_parse_config_file("/init.rc");

其代码实现如下:

int init_parse_config_file(const char *fn)
{char *data;data = read_file(fn, 0);        //read_file()调用open\lseek\read 将init.rc读出来if (!data) return -1;parse_config(fn, data);        //调用parse_config开始解析DUMP();return 0;
}

parse_config() 代码:

static void parse_config(const char *fn, char *s)
{struct parse_state state;struct listnode import_list;struct listnode *node;char *args[INIT_PARSER_MAXARGS];int nargs;nargs = 0;state.filename = fn;    //文件名state.line = 0;state.ptr = s;          //文字指针state.nexttoken = 0;state.parse_line = parse_line_no_op;list_init(&import_list);state.priv = &import_list;for (;;) {switch (next_token(&state)) {                   //next_token()根据从state.ptr开始遍历case T_EOF:                                     //遍历到文件结尾,然后goto解析import的.rc文件state.parse_line(&state, 0, 0);goto parser_done;case T_NEWLINE:                                 //到了一行结束state.line++;if (nargs) {int kw = lookup_keyword(args[0]);      //找到这一行的关键字if (kw_is(kw, SECTION)) {                        //如果这是一个section的第一行                                            state.parse_line(&state, 0, 0);parse_new_section(&state, kw, nargs, args);} else {                                         //如果这不是一个section的第一行state.parse_line(&state, nargs, args);}nargs = 0;}break;case T_TEXT:                                            //遇到普通字符if (nargs < INIT_PARSER_MAXARGS) {args[nargs++] = state.text;}break;}}
parser_done:list_for_each(node, &import_list) {struct import *import = node_to_item(node, struct import, list);int ret;INFO("importing '%s'", import->filename);ret = init_parse_config_file(import->filename);if (ret)ERROR("could not import file '%s' from '%s'\n",import->filename, fn);}
}

next_token() 解析完 init.rc 中一行之后,
会返回T_NEWLINE,这时调用 lookup_keyword 函数来找出这一行的关键字, lookup_keyword返回的是一个整型值,对应keyword_info[]数组的下标,keyword_info[]存放的是keyword_info结构体类型的数据,

struct {const char *name;                      //关键字的名称int (*func)(int nargs, char **args);   //对应的处理函数unsigned char nargs;                   //参数个数unsigned char flags;                   //flag标识关键字的类型,包括COMMAND、OPTION、SECTION
} keyword_info

因此keyword_info[]中存放的是所有关键字的信息,每一项对应一个关键字。
根据每一项的flags就可以判断出关键字的类型,如新的一行是SECTION,就调用parse_new_section()来解析这一行,
如新的一行不是一个SECTION的第一行,那么调用state.parseline()来解析(state.parseline所对应的函数会根据section类型的不同而不同),在parse_new_section()中进行动态设置。

三种类型的section: service、on、import,
service对应的state.parseline为parse_line_service,
on对应的state.parseline为parse_line_action,
import section中只有一行所以没有对应的state.parseline。

这篇关于Android init.rc文件详解的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1122345

相关文章

Spring Security基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

OpenHarmony鸿蒙开发( Beta5.0)无感配网详解

1、简介 无感配网是指在设备联网过程中无需输入热点相关账号信息,即可快速实现设备配网,是一种兼顾高效性、可靠性和安全性的配网方式。 2、配网原理 2.1 通信原理 手机和智能设备之间的信息传递,利用特有的NAN协议实现。利用手机和智能设备之间的WiFi 感知订阅、发布能力,实现了数字管家应用和设备之间的发现。在完成设备间的认证和响应后,即可发送相关配网数据。同时还支持与常规Sof

Android实现任意版本设置默认的锁屏壁纸和桌面壁纸(两张壁纸可不一致)

客户有些需求需要设置默认壁纸和锁屏壁纸  在默认情况下 这两个壁纸是相同的  如果需要默认的锁屏壁纸和桌面壁纸不一样 需要额外修改 Android13实现 替换默认桌面壁纸: 将图片文件替换frameworks/base/core/res/res/drawable-nodpi/default_wallpaper.*  (注意不能是bmp格式) 替换默认锁屏壁纸: 将图片资源放入vendo

Android平台播放RTSP流的几种方案探究(VLC VS ExoPlayer VS SmartPlayer)

技术背景 好多开发者需要遴选Android平台RTSP直播播放器的时候,不知道如何选的好,本文针对常用的方案,做个大概的说明: 1. 使用VLC for Android VLC Media Player(VLC多媒体播放器),最初命名为VideoLAN客户端,是VideoLAN品牌产品,是VideoLAN计划的多媒体播放器。它支持众多音频与视频解码器及文件格式,并支持DVD影音光盘,VCD影

6.1.数据结构-c/c++堆详解下篇(堆排序,TopK问题)

上篇:6.1.数据结构-c/c++模拟实现堆上篇(向下,上调整算法,建堆,增删数据)-CSDN博客 本章重点 1.使用堆来完成堆排序 2.使用堆解决TopK问题 目录 一.堆排序 1.1 思路 1.2 代码 1.3 简单测试 二.TopK问题 2.1 思路(求最小): 2.2 C语言代码(手写堆) 2.3 C++代码(使用优先级队列 priority_queue)

K8S(Kubernetes)开源的容器编排平台安装步骤详解

K8S(Kubernetes)是一个开源的容器编排平台,用于自动化部署、扩展和管理容器化应用程序。以下是K8S容器编排平台的安装步骤、使用方式及特点的概述: 安装步骤: 安装Docker:K8S需要基于Docker来运行容器化应用程序。首先要在所有节点上安装Docker引擎。 安装Kubernetes Master:在集群中选择一台主机作为Master节点,安装K8S的控制平面组件,如AP

android-opencv-jni

//------------------start opencv--------------------@Override public void onResume(){ super.onResume(); //通过OpenCV引擎服务加载并初始化OpenCV类库,所谓OpenCV引擎服务即是 //OpenCV_2.4.3.2_Manager_2.4_*.apk程序包,存

从状态管理到性能优化:全面解析 Android Compose

文章目录 引言一、Android Compose基本概念1.1 什么是Android Compose?1.2 Compose的优势1.3 如何在项目中使用Compose 二、Compose中的状态管理2.1 状态管理的重要性2.2 Compose中的状态和数据流2.3 使用State和MutableState处理状态2.4 通过ViewModel进行状态管理 三、Compose中的列表和滚动

嵌入式Openharmony系统构建与启动详解

大家好,今天主要给大家分享一下,如何构建Openharmony子系统以及系统的启动过程分解。 第一:OpenHarmony系统构建      首先熟悉一下,构建系统是一种自动化处理工具的集合,通过将源代码文件进行一系列处理,最终生成和用户可以使用的目标文件。这里的目标文件包括静态链接库文件、动态链接库文件、可执行文件、脚本文件、配置文件等。      我们在编写hellowor

LabVIEW FIFO详解

在LabVIEW的FPGA开发中,FIFO(先入先出队列)是常用的数据传输机制。通过配置FIFO的属性,工程师可以在FPGA和主机之间,或不同FPGA VIs之间进行高效的数据传输。根据具体需求,FIFO有多种类型与实现方式,包括目标范围内FIFO(Target-Scoped)、DMA FIFO以及点对点流(Peer-to-Peer)。 FIFO类型 **目标范围FIFO(Target-Sc