Android 系统启动之 Init 进程启动分析四
作者:访客发布时间:2023-12-21分类:程序开发学习浏览:103
本文基于 AOSP android-10.0.0_r41 版本讲解,内核版本 android-goldfish-4.14-gchips
second_stage 接下来就会开始解析执行 init.rc 文件,在看代码之前我们先了解一下 init.rc 文件的规则
1. init.rc 文件格式
init.rc 文件是以块 (section)为单位的,,一个块可以包含多行。块分成两大类:一类称为动作(action),另一类称为服务(service)。
- 动作(action):以关键字 on 开头,表示在某个时候执行一堆命令
- 服务(service):以关键字 service 开头,表示启动某个进程的方式和参数
块 (section)以关键字 on
或者 service
开始,直到下一个 on
或者 service
结束,中间所有行都属于这个块 (section)
接着我们看两个示例:
on init
sysclktz 0
# Backward compatibility.
symlink /system/etc /etc
symlink /sys/kernel/debug /d
# ......
这个 section 表示在系统启动(init)时,执行下面的一堆命令。
service adbd /sbin/adbd
user adb
group adb
这里定义了一个服务 adbd,对应的执行文件是 /sbin/adbd
,接着定义了服务的两个属性 user 和 group
另外,init.rc 中的注释以 #
开头。
2. init.rc 脚本语法
2.1 动作(action)
动作(action)的一般格式如下:
on <trigger> # 触发条件
<command> # 执行命令
<command1> # 可以执行多个命令
在动作(action)里面的,on 后面跟着的字符串是触发器(trigger),trigger 是一个用于匹配某种事件类型的字符串,当事件发生时,就会执行 trigger 下面的 command
触发器(trigger)有几种格式,最简单的一种是一个单纯的字符串。比如on boot
,表示系统启动时。还有一种常见的格式是 on property<属性>=<值>
。如果属性值在运行时设成了指定的值,则action 中的命令列表就会执行。
常见的 trigger 有以下几种:
- on early-init:在初始化早期阶段触发
- on init:在初始化阶段触发
- on late-init:在初始化晚期阶段触发
- on boot/charger:当系统启动/充电时触发
- on property:当属性值满足条件时触发
command 是 action 的命令列表中的命令,或者是 service 中的 onrestart 选项的参数命令。
命令将在所属事件发生时被一个个地执行
常见命令有以下这些:
exec <path> [ <argument> ]*:运行指定路径下的程序,并传递参数
export <name> <value>:设置全局环境参数。此参数被设置后对全部进程都有效
ifup <interface>:使指定的网络接口"上线",相当激活指定的网络接口
import <filename>:导入一个额外的 rc 配置文件
hostname <name>:设置主机名
chdir <directory>:改变工作文件夹
chmod <octal-mode> <path>:设置指定文件的读取权限
chown <owner> <group> <path>:设置文件所有者和文件关联组
chroot <directory>:设置根文件夹
class_start <serviceclass>:启动指定类属的全部服务,假设服务已经启动,则不再反复启动
class_stop <serviceclass>:停止指定类属的全部服务
domainname <name>:设置域名
insmod <path>:安装模块到指定路径
mkdir <path> [mode] [owner] [group]:用指定参数创建一个文件夹
mount <type> <device> <dir> [ <mountoption> ]*:类似于linux的mount指令
setprop <name> <value>:设置属性及相应的值
setrlimit <resource> <cur> <max>:设置资源的rlimit
start <service>:假设指定的服务未启动,则启动它
stop <service>:假设指定的服务当前正在执行。则停止它
symlink <target> <path>:创建一个符号链接
sysclktz <mins_west_of_gmt>:设置系统基准时间
trigger <event>:触发另一个时间
write <path> <string> [ <string> ]*:往指定的文件写字符串
2.2 服务(service)
服务(service)的一般格式如下:
service <name><pathname> [ <argument> ]*
<option>
<option>
- name:表示此服务的名称
- pathname:可执行文件对应的路径
- argument:执行可执行文件时传入的参数
- option:服务的选项
服务的选项主要有:
-
class <name> [ <name>\* ]:为服务指定 class 名字。 同一个 class 名字的服务会被一起启动或退出, 默认值是 default
-
console [<console>]:这个选项表明服务需要一个控制台。 第二个参数 console 的意思是可以设置你想要的控制台类型,默认控制台是 /dev/console, /dev 这个前缀通常是被省略的, 比如你要设置控制台 /dev/tty0, 那么只需要设置为console tty0 即可。
-
critical:表示服务是严格模式。 如果这个服务在4分钟内或者启动完成前退出超过4次,那么设备将重启进入 bootloader 模式
-
disabled:这个服务不会随着 class 一起启动。只能通过服务名来显式启动。比如 foobar 服务的 class 是 core, 且是 disabled 的,当执行 class_start core 时,foobar 服务是不会被启动的。 foobar 服务只能通过 start foobar 这种方法来启动。
-
file <path> <type> 根据文件路径 path 来打开文件,然后把文件描述符 fd 传递给服务进程。type 表示打工文件的方式,只有三种取值 r, w, rw。对于 native 程序来说,可以通过 libcutils 库提供的 android_get_control_file() 函数来获取传递过来的文件描述符。举个例子, logd.rc 部分内容如下:
service logd /system/bin/logd
socket logd stream 0666 logd logd
socket logdr seqpacket 0666 logd logd
socket logdw dgram+passcred 0222 logd logd
file /proc/kmsg r
file /dev/kmsg w
user logd
其中通过 file /proc/kmsg r 以只读方式打开了设备文件 /proc/kmsg, 然后在代码中这么获取打开的文件, 见 sytem/core/logd/main.cpp
main 函数:
static const char dev_kmsg[] = "/dev/kmsg";
fdDmesg = android_get_control_file(dev_kmsg);
if (fdDmesg < 0) {
fdDmesg = TEMP_FAILURE_RETRY(open(dev_kmsg, O_WRONLY | O_CLOEXEC));
}
这里可能有点奇怪,为什么要通过 file 这个选项来打开文件,而不直接在代码里面通过 open() 函数来打开呢?我觉得主要是权限问题,还是以 logd 为例子。/dev/kmsg
的权限是:
generic_x86_64:/ # ls -l /dev/kmsg
crw------- 1 root root 1, 11 2023-12-04 12:14 /dev/kmsg
只有 root 用户可读写。而 logd 服务是以 user logd 选项来启动的,自然没有权限用 open() 函数来打开 /dev/kmsg 这个设备文件。file 选项则可以通过 init 进程把文件打开,然后把文件描述符传递给子进程, 从而解决了权限的问题。
- group <groupname> [ <groupname>\* ]:
在启动 Service 前,将 Service 的用户组改为第一个 groupname, 第一个 groupname 是必须有的, 第二个 groupname 可以不设置,用于追加组(通过setgroups)。目前默认的用户组是 root 组。
-
oneshot:当服务退出的时候,不自动重启。适用于那些开机只运行一次的服务。
-
onrestart:在服务重启的时候执行一个命令
-
seclabel <seclabel>:在启动 Service 前设置指定的 seclabel,默认使用init的安全策略。 主要用于在 rootfs 上启动的 service,比如 ueventd, adbd。 在系统分区上运行的 service 有自己的 SELinux安全策略。
-
setenv <name> <value>:设置进程的环境变量
-
socket <name> <type> <perm> [ <user> [ <group> [ <seclabel> ] ] ]
创建一个 unix domain socket, 路径为 /dev/socket/name
, 并将 fd 返回给 Service。 type 只能是 dgram
, stream
or seqpacket
。user 和 group 默认值是 0。 seclabel 是这个 socket 的 SELinux security context, 它的默认值是 service 的 security context 或者基于其可执行文件的 security context。
- user <username> 在启动 Service 前修改进程的所属用户, 默认启动时 user 为 root
最后,我们看个例子:
service bootanim /system/bin/bootanimation
class core //给服务指定一个类属,这样方便操作多个服务同时启动或停止
user graphics //在执行此服务之前先切换用户名
group graphics audio
disabled //这个服务不会随着 class 一起启动
oneshot //当此服务退出时不会自动重启
本文介绍了 init.rc 的基本结构与常用的一些配置选项,日常工作中遇到不懂的一些配置,可以查阅源码中的文档 system/core/init/README.md
参考资料
- Android系统开发进阶-init.rc 详解
- 我是init进程
- Android系统启动——3init.rc解析
- Android系统启动之init.rc文件解析过程
关于
我叫阿豪,2015 年本科毕业于国防科学技术大学指挥信息系统专业,毕业后从事信息化装备的研发工作,工作内容主要涉及 Android Framework 与 Linux Kernel。
如果你对 Android Framework 感兴趣或者正在学习 Android Framework,可以关注我的微信公众号和抖音,我会持续分享我的学习经验,帮助正在学习的你少走一些弯路。学习过程中如果你有疑问或者你的经验想要分享给大家可以添加我的微信,我拉你进技术交流群。
相关推荐
- 轻松上手:
(三)笔记可再编辑 - 如何在iPhone,iPad和Android上使用WordPress应用程序
- 一款简单高效的Android异步框架
- [Android][NDK][Cmake]一文搞懂Android项目中的Cmake
- Android---View中的setMinWidth与setMinimumWidth的踩坑记录
- Android广播如何解决Sending non-protected broadcast问题
- 有关Android Binder面试,你未知的9个秘密
- 开启Android学习之旅-2-架构组件实现数据列表及添加(kotlin)
- Android低功耗蓝牙开发总结
- Android 通知文本颜色获取
- 程序开发学习排行
-
- 1鸿蒙HarmonyOS:Web组件网页白屏检测
- 2HTTPS协议是安全传输,为啥还要再加密?
- 3HarmonyOS鸿蒙应用开发——数据持久化Preferences
- 4记解决MaterialButton背景颜色与设置值不同
- 5鸿蒙HarmonyOS实战-ArkUI组件(RelativeContainer)
- 6鸿蒙HarmonyOS实战-ArkUI组件(Stack)
- 7[Android][NDK][Cmake]一文搞懂Android项目中的Cmake
- 8Android广播如何解决Sending non-protected broadcast问题
- 9鸿蒙HarmonyOS实战-ArkUI组件(mediaquery)
- 最近发表
-
- WooCommerce最好的WordPress常用插件下载博客插件模块的相关产品
- 羊驼机器人最好的WordPress常用插件下载博客插件模块
- IP信息记录器最好的WordPress常用插件下载博客插件模块
- Linkly for WooCommerce最好的WordPress常用插件下载博客插件模块
- 元素聚合器Forms最好的WordPress常用插件下载博客插件模块
- Promaker Chat 最好的WordPress通用插件下载 博客插件模块
- 自动更新发布日期最好的WordPress常用插件下载博客插件模块
- WordPress官方最好的获取回复WordPress常用插件下载博客插件模块
- Img to rss最好的wordpress常用插件下载博客插件模块
- WPMozo为Elementor最好的WordPress常用插件下载博客插件模块添加精简版