android rc 语法介绍

以init.rc为例。

  • on early-init; 在初始化早期阶段触发;

  • on init; 在初始化阶段触发;

  • on late-init; 在初始化晚期阶段触发;

  • on boot/charger: 当系统启动/充电时触发,还包含其他情况,此处不一一列举;

  • on property:=: 当属性值满足条件时触发;

.rc文件

init.rc文件由系统第一个启动的init程序解析。是启动系统服务使用的文件。

rc规则主要包含了四种类型的语句:

  1. Action

  1. Commands

  1. Services

  1. Options.

Action和services显式声明了一个语句块,而commands和options属于最近声明的语句块。

 

在第一个语句块之前 的commands和options会被忽略.

基本规则如下(基本上与bash语法一样):

注释是以#开头。

在init.rc文件中一条语句通常是占据一行.

单词之间是通过空格符来相隔的.如果需要在单词内使用空格,那么得使用转义字符"",

如果在一行的末尾有一个反斜杠,那么是换行折叠符号,应该和下一行合并成一起来处理,与C语言中的含义是一致的。

系统的定义property 前缀。

system, vendor, odm, 或者 product 分区下的所有 binaries services 都有一个对应的 .rc 文件。这些 .rc 文件都放在各分区的 $partion/etc/init 目录下。Android.mk 中提供了一个 LOCAL_INIT_RC 配置, Android.bp 中也提供了一个 init_rc 配置。这两个配置可以为服务指定它的 .rc 文件。这里需要说明的是 service bin 编译到哪个分区,它对应的 .rc 文件也会编译到对应分区的 etc/init 目录。

关键字

关键字含义
token在计算机身份认证中是令牌(临时)的意思,在词法分析中是标记的意思。一般作为邀请、登录系统使用。
Section语句块,相当于C语言中大括号内的一个块。一个Section以Service或On开头.
以Service开头的Section叫做服务
而以On开头的叫做动作(Action).
services服务
Action动作
commands命令
options选项
trigger触发条件
class类属,即能够为多个service指定一个同样的类属,方便操作同一时候启动或停止.

Action(动作)

动作表示了一组命令(commands)组成.动作包括一个触发器,决定了何时运行这个动作。

注意:当触发器的条件满足时,这个动作会被增加到已被运行的队列尾。假设此动作在队列中已经存在,那么它将不会运行.

一个动作所包括的命令将被依次运行。

 

on <trigger> ## 触发条件 <command> ##执行命令 <command1> ##可以执行多个命令

trigger(触发器)

在"动作"(action)里面的,on后面跟着的字符串是触发器(trigger),trigger是一个用于匹配某种事件类型的字符串,它将对应的Action的执行。

触发器(trigger)有几种格式:

1、最简单的一种是一个单纯的字符串。比如“on boot”。这种简单的格式可以使用命令"trigger"来触发。 2、还有一种常见的格式是"on property<属性>=<值>"。如果属性值在运行时设成了指定的值,则"块"(action)中的命令列表就会执行。

常见的格式:

格式含义
on early-init在初始化早期阶段触发
on init在初始化阶段触发
on late-init在初始化晚期阶段触发
on boot/charger当系统启动/充电时触发
on property当属性值满足条件时触发

例如:

 

on property:vendor.sys.boot_mode=normal write ${persist.vendor.mmi.misc_dev_path} "normal" on boot chown bluetooth bluetooth /sys/module/bluetooth_power/parameters/power chown bluetooth net_bt /sys/class/rfkill/rfkill0/type chown bluetooth net_bt /sys/class/rfkill/rfkill0/state chown bluetooth bluetooth /proc/bluetooth/sleep/proto

commands(命令)

command是action的命令列表中的命令,或者是service中的选项 onrestart 的参数命令.

命令将在所属事件发生时被一个个地执行.

常见命令:

命令描写叙述
exec <path> [ <argument> ]*运行指定路径下的程序,并传递參数
export <name> <value>设置全局环境參数。此參数被设置后对全部进程都有效
ifup <interface>使指定的网络接口"上线",相当激活指定的网络接口
import <filename>导入一个额外的init配置文件
hostname <name>设置主机名
chdir <directory>改变工作文件夹
chmod <octal-mode> <path>改变指定文件的读取权限
chown <owner> <group> <path>改变指定文件的拥有都和组名的属性
chroot <directory>改变进行的根文件夹
`class_start ``启动指定类属的全部服务,假设服务已经启动,则不再反复启动
class_stop <serviceclass>停止指定类属的所有服务
domainname <name>设置域名
insmod <path>安装模块到指定路径
mkdir <path> [mode] [owner] [group]用指定參数创建一个文件夹,在默认情况下,创建的文件夹读取权限为755
username为root,组名为root.
mount <type> <device> <dir> [ <mountoption> ]*类似于linux的mount指令
setkey TBD(To Be Determined),待定
setprop <name> <value>设置属性及相应的值
setrlimit <resource> <cur> <max>设置资源的rlimit(资源限制),不懂就百度一下rlimit
start <service>假设指定的服务未启动,则启动它
stop <service>假设指定的服务当前正在执行,则停止它
symlink <target> <path>创建一个符号链接
sysclktz <mins_west_of_gmt>设置系统基准时间
trigger <event>触发一个事件,Used to queue an action from another action.
write <path> <string> [ <string> ]*往指定的文件写字符串
  • exec [ <seclabel> [ <user> [ <group>\* ] ] ] -- <command> [ <argument>\* ] 新建一个子进程并运行一个带指定参数的命令。 命令跟在 -- 后面,以便前面可以指定 seclabel(安全策略),user(所有者),group(用户组)等选项。 直到这个命令运行完才可以运行其他命令。seclabel 可以设置为 - 表示用默认值, argument 可以使用属性扩展形式 ${property}。 直到子进程新建完毕,init进程才继续执行.

  • exec_background [ <seclabel> [ <user> [ <group>\* ] ] ] -- <command> [ <argument>\* ] 与 exec 相似,差别在于 exec_background 不会阻塞 init 进程的运行。

services(服务)

服务是指那些须要在系统初始化时就启动或退出时自己主动重新启动的程序

 

service <name><pathname> [ <argument> ]* <option> <option>

解释一下各个参数:

参数含义
name表示此服务的名称
pathname此服务所在路径因为是可执行文件,所以一定有存储路径。
argument启动服务所带的参数
option对此服务的约束选项

option(选项)

options是Service的修订项。它们决定一个服务何时以及如何运行.

选项描述
critical据设备相关的关键服务,如果在4分钟内,此服务重复启动了4次,那么设备将会重启进入还原模式。
disabled服务不会自动运行,必须显式地通过服务器来启动。
setenv设置环境变量
socket [ [ ] ]在/dev/socket/下创建一个unix domain的socket,并传递创建的文件描述符fd给服务进程.其中type必须为dgram或stream,seqpacket.用户名和组名默认为0
user在执行此服务之前先切换用户名。当前默认为root.
group [ ]*类似于user,切换组名
oneshot当此服务退出时不会自动重启.
class给服务指定一个类属,这样方便操作多个服务同时启动或停止.默认情况下为default.
onrestart当服务重启时执行一条指令,

使用例子:

 

service bootanim /system/bin/bootanimation class core //给服务指定一个类属,这样方便操作多个服务同时启动或停止 user graphics //在执行此服务之前先切换用户名 group graphics audio disabled //服务不会自动运行 oneshot //当此服务退出时不会自动重启 on property:vendor.dms.enable=1 // 当属性vendor.dms.enable 为1时触发 chmod 0777 /mnt/obb //改变/mnt/obb 操作权限 touch /mnt/obb/raw_driver //创建raw_driver文件 chmod 0777 /mnt/obb/raw_driver symlink /vendor/bin/dms_release /dms_release //给 /vendor/bin/dms_release 创建软链接 start dms_server //启动定义的服务

rc文件实例

 

# not complete -- just providing some examples of usage # on boot export PATH /sbin:/system/sbin:/system/bin export LD_LIBRARY_PATH /system/lib mkdir /dev mkdir /proc mkdir /sys mount tmpfs tmpfs /dev mkdir /dev/pts mkdir /dev/socket mount devpts devpts /dev/pts mount proc proc /proc mount sysfs sysfs /sys write /proc/cpu/alignment 4 ifup lo hostname localhost domainname localhost mount yaffs2 mtd@system /system mount yaffs2 mtd@userdata /data import /system/etc/init.conf class_start default service adbd /sbin/adbd user adb group adb service usbd /system/bin/usbd -r user usbd group usbd socket usbd 666 service zygote /system/bin/app_process -Xzygote /system/bin --zygote socket zygote 666 service runtime /system/bin/runtime user system group system on device-added-/dev/compass start akmd on device-removed-/dev/compass stop akmd service akmd /sbin/akmd disabled user akmd group akmd

rc文件解析

源码路径system/core/init/init.cpp中:

 

parser.ParseConfig("/init.rc");

开始解析rc文件.

ParseConfig函数在文件core/init/init_parser.cpp140行:

 

bool Parser::ParseConfig(const std::string& path) { if (is_dir(path.c_str())) { return ParseConfigDir(path); } return ParseConfigFile(path); }

ParseConfigFile函数:

 

bool Parser::ParseConfigFile(const std::string& path) { LOG(INFO) << "Parsing file " << path << "..."; Timer t; std::string data; if (!read_file(path, &data)) { return false; } data.push_back(' '); // TODO: fix parse_config. ParseData(path, data); for (const auto& sp : section_parsers_) { sp.second->EndFile(path); } LOG(VERBOSE) << "(Parsing " << path << " took " << t << ".)"; return true; }

参考

Android init.rc文件浅析

安卓系统启动--3init.rc解析

init.rc深入学习

添加te文件

作为 Android 安全模型的一部分,Android 使用安全增强型 Linux (SELinux) 对所有进程强制执行强制访问控制 (MAC),甚至包括以 Root/超级用户权限运行的进程(Linux 功能)。

SELinux 可以在各种模式下实现: 宽容模式 - 仅记录但不强制执行 SELinux 安全政策。 强制模式 - 强制执行并记录安全政策。如果失败,则显示为 EPERM 错误。 在选择强制执行级别时只能二择其一,您的选择将决定您的政策是采取操作,还是仅允许您收集潜在的失败事件。宽容模式在实现过程中尤其有用。

在开发环境可以通过:

 

setenforce 0 //宽容模式 setenforce 1 // 强制模式

标签、规则和域

SELinux 依靠标签来匹配操作和政策。标签用于决定允许的事项。套接字、文件和进程在 SELinux 中都有标签。SELinux 在做决定时需参照两点:一是为这些对象分配的标签,二是定义这些对象如何交互的政策。

在 SELinux 中,标签采用以下形式:user:role:type:mls_level

  • user :

  • role :

  • type : 是访问决定的主要组成部分,可通过构成标签的其他组成部分进行修改。对象会映射到类,对每个类的不同访问类型由权限表示。

  • mls_level:

 

u:object_r:dms_exec:s0

规则和域

政策规则采用以下形式:allow domains types:classes permissions;,其中:

  • Domain - 一个进程或一组进程的标签。也称为域类型,因为它只是指进程的类型。

  • Type - 一个对象(例如,文件、套接字)或一组对象的标签。

  • Class - 要访问的对象(例如,文件、套接字)的类型。

  • Permission - 要执行的操作(例如,读取、写入)。

 

allow appdomain app_data_file:file rw_file_perms;

 

// file_context #dms /vendor/bin/dms u:object_r:dms_exec:s0 //dms.te type dms,domain; type dms_exec,exec_type,file_type,vendor_file_type; init_daemon_domain(dms) net_domain(dms)

参考

AOSP-安全性-功能

加入编译

Android.mk 用预编译,将可执行文件加入系统中。

 

LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := dms LOCAL_SRC_FILES := dms LOCAL_INIT_RC := dms.rc LOCAL_MODULE_TAGS := optional LOCAL_MODULE_CLASS := EXECUTABLES LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR_EXcECUTABLES) include $(BUILD_PREBUILT)

参考

Android mk 引用 jar 包、so 库、aar 包,系统签名 Android系统开发进阶-Android编译系统介绍

调试

 

1. setprop vendor.dms.enable 1 //通过条件触发 or start dms_server //启动dms_server 2. logcat -b all -s init // 查看init进程log3. ps -ef | grep dms //查看dms进程id

init.rc解析

简单来说,init.rc是安卓的初始化语言,具有固定的语法。作用是在安卓启动阶段做一下初始化操作。

下面举一个使用的小例子,关于init.rc触发器的使用。

init.rc中的触发器细分为事件触发器和属性触发器。

事件触发器是由’trigger’命令或init可执行文件中的QueueEventTrigger()函数触发的字符串。它们采用简单字符串的形式,例如’boot’或’late-init’。

属性触发器是在命名属性将值更改为给定新值或命名属性将值更改为任何新值时触发的字符串。它们分别采用’property:='和’property:= *'的形式。在init的初始引导阶段,还会相应地评估和触发属性触发器。

Action可以有多个属性触发器,但可能只有一个事件触发器。

on boot

# Trigger start evs_driver service

start evs_driver

1

2

3

boot是一个事件触发器,当安卓开机发生boot事件,启动evs_driver服务.

on property:a=b && property:c=d

start evs_app

1

2

on property:a=b && property:c=d 定义了三次执行的操作:

在初始引导期间,如果属性a = b且属性c = d。

任何时候属性a转换为值b,而属性c已经等于d。

任何时候属性c转换为值d,而属性a已经等于b。

当条件满足时,启动evs_app服务。

也可以事件触发器和属性触发器一起使用:

on boot && property:a=b

start evs_driver

1

2

制造商init.rc可能存放的路径:vendor\etc\init\hw

增加一个rc

0. 在Android.mk 同目录下新建文件haha.sh (文件名任意),执行shell 操作, 以下简单举例

#!/bin/sh

1. 在Android.mk 同目录下新建文件test.rc (文件名任意)

含义:当设置系统属性persist.vendor.test.haha=2时,启动服务,执行shell 脚本

on property:persist.vendor.test.haha=2

start haha-sh

service haha-sh /vendor/bin/haha.sh

class main

user root

group root

disabled

oneshot

2. 在Android.mk 中添加配置

LOCAL_INIT_RC := test.rc

3. 在型号添加配置模块的mk 文件中添加以下内容,将代码中的sh 文件copy 到vendor/bin 目录下

PRODUCT_COPY_FILES += \

vendor/apps/TestApp/haha.sh:$(TARGET_COPY_OUT_VENDOR)/bin/haha.sh \

在默认情况下,通过init程序启动的程序的标准输出stdout和标准错误输出stderr会重定向到/dev/null.如:

1service akmd /system/bin/logwrapper /sbin/akmd

为了更方便调试你的程序,你可以使用Android的log系统,标准输出和标准错误输出会重定义到Android的log系统中来.

那么要添加自定义的property怎么添加呢?

1.

/system/sepolicy/private/property_contexts

/system/sepolicy/prebuilts/api/28.0/private/property_contexts

在这两个文件内添加property定义

android. u:object_r:system_prop:s0

2.

/system/sepolicy/private/platform_app.te

/system/sepolicy/prebuilts/api/28.0/private/platform_app.te

这两个文件中设置property权限,按照规则allow scontex tcontex:tclass action

allow platform_app system_prop:property_service set;

https://www.likecs.com/show-402175.html

  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值