Android系统rc启动文件解析

近期学习Android系统rc启动文件的一些记录。
Views: 688
3 0
Read Time:3 Minute, 23 Second

无论是在Android系统还是在Linux系统中,rc启动文件都是一个非常重要的东西。在这些启动文件内,规定了我们的系统在开机过程中所要完成的一些事,今天这篇文章将对Android系统中的rc启动文件做一个解析。

系统启动流程

安卓系统的启动由Linux系统的启动演化而来。在系统上电后,系统内核就开始解析配置文件(也就是init.rc),这一块儿的源代码位于system/core/init/init.c内。

在main函数内,会逐次执行restart_processes- >restart_service_if_needed->service_start这些函数,逐步完成整个系统的启动。

大体上流程可以以下图表示:

rc启动文件简介

在Linux与Android系统内,用户态与内核态需要进行数据交互,而很多这些交互实际上都需要文件作为沟通媒介(Linux系统的哲学:一切皆文件)。在内核启动以后,往往会立即跟用户态的程序进行数据交换,所在在我们内核启动的过程中就需要创建好这些文件,那么rc文件主要的作用就是创建这些用于通信的文件(包括分区挂载)并对其做相关操作的,当然也包含一些对系统服务的操作。

需要说明的是,rc启动文件并不是源码文件,rc启动文件只是满足了特定语法规则的解释文件,用于描述系统在某个环节执行相应的操作。在我们的系统内,rc启动文件其实有很多个。在系统启动过程重根目录下的init.rc是最先被加载执行的启动文件,其会被init进程加载。

在init进程中,会mount包括/system、/vendor等分区。在加载init.rc之后会接着加载/system/etc/init、/vendor/etc/init以及/odm/etc/init、/product/etc/init等目录下的rc文件。各个目录下的rc文件具有不同的作用,一般来说按照如下划分:

/system/etc/init/ 用于系统本身,比如 SurfaceFlinger, MediaService, and logcatd。

/vendor/etc/init/ 用于SoC(系统级核心厂商,如高通), 为他们提供一些核心功能和服务。

/odm/etc/init/ 用于设备制造商(odm定制厂商,如华为、小米),为他们的传感器或外围设备提供一些核心功能和服务。

/product/etc/init/ 用于产品机型的配置。

对于很多系统级别的服务,在拥有自己独立的二进制执行文件时,也都拥有自己的rc启动文件。在Android.mk内可以通过LOCAL_INIT_RC指定rc启动文件,在Android.bp内也提供了一个init_rc配置项

rc启动文件语法结构

rc启动文件包含五个主要的部分,分别是:Actions,Commands,Services,Options,Imports。以下将分别介绍这几个部分。

Actions:从字面意义来看,这代表具体的行为。在rc启动文件中,Actions的部分都以on开头,其语法规则如下:

on <trigger> [&& <trigger>]*
   <command>
   <command>
   <command>

这其中trigger代表具体的触发时机,trigger分为event triggersproperty triggers。每一个Action可以存在多个trigger,但至少得有一个event trigger。如下面的例子 on property:a=b && property:c=d,这代表该Action将会在属性a与属性b相等iqe属性c与属性d相等时执行。

而所有的event triggers其实是有一个次序的,当前所有的次序如下:

early-init:cgroups配置完成

init:系统冷启动完成

charger:ro.bootmode == “charger”

late-init:ro.bootmode != “charger”

early-fs:Vold服务启动

fs:Vold启动完成,开始mount分区

post-fs:Configure anything dependent on early mount

last-fs:Mount partitions marked as latemounted.

post-fs-data:挂载data分区

zygote-start:启动zygote进程

early-boot:zygote启动完成

boot:启动完成

Commands:Commands指的是具体执行的命令。这些命令包括:chmod、chown、copy、enable、exec、exec_start、export、ifup、load_system_props、load_persist_props、mkdir、mount、restart、rmdir、setprop、symlink等等,以下列出了一些Commands的具体含义:

命令描写叙述
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 <serviceclass>启动指定类属的全部服务,假设服务已经启动,则不再反复启动.
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> Trigger an event. Used to queue an action from another action.这名话没有理解,望高手指点.
write <path> <string> [ <string> ]*往指定的文件写字符串.

关于这部分的细节,可以参考Android官方文档:https://android.googlesource.com/platform/system/core/+/master/init/README.md

Services:Service代指系统中运行的具体的服务在rc文件中其语法结构为:

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

其中<name>指代该服务名称,<pathname>指向可执行文件所在的路径,[<argument>]为该可执行文件所能接受的参数,同时我们可以借助Options来对该服务进行一些额外的设定,如设定用户、用户组等,这里给出一个示例:

service evs_app /system/bin/evs_app
    class hal
    priority -20
    user root
    group root
    disabled # will not automatically start with its class; must be explictly started.

在定义好服务后,如果未设定服务自启动,我们需要显示地通过start命令来启动。

Options:Options是用于修饰Service的,他们会影响init服务器在何时以及怎样去运行这些服务。一些常见的Options如下:

选项描述
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当服务重启时执行一条指令,

Imports:用于导入外部配置文件或者其他rc启动文件

以下为一个简单的rc启动文件,作为示例,大家可以对照着解析其中的内容:

#  
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  

好啦,以上就是本篇博客的全部内容,希望能够对大家有所帮助哦~

Happy
Happy
0 %
Sad
Sad
0 %
Excited
Excited
0 %
Sleepy
Sleepy
0 %
Angry
Angry
0 %
Surprise
Surprise
0 %
FranzKafka95
FranzKafka95

极客,文学爱好者。如果你也喜欢我,那你大可不必害羞。

Articles: 83

Leave a Reply

Your email address will not be published. Required fields are marked *

en_USEN