centos 怎么退出init 3_Android 10.0系统启动之init进程(四)-「Android取经之路」

感谢您的阅读与点赞!欢迎点击右上角关注:「大猫玩程序」VX公众号:大猫玩程序
9d6e436ee41ff92042978bd8ccda53f7.png

上一节主要讲解了Init进程的第二阶段启动过程以及信号处理过程。

Android 10.0系统源码取经之路——启动篇

Android系统架构浅析-「Android取经之路」

Android是怎么启动的-「Android取经之路」

Android 10.0系统启动之init进程(一)-「Android取经之路」

Android 10.0系统启动之init进程(二)-「Android取经之路」

Android 10.0系统启动之init进程(三)-「Android取经之路」

本节主要讲解init进程第二阶段的属性服务和init.rc启动流程

6.属性服务

我们在开发和调试过程中看到通过property_set可以轻松设置系统属性,那干嘛这里还要启动一个属性服务呢?这里其实涉及到一些权限的问题,不是所有进程都可以随意修改任何的系统属性,

Android将属性的设置统一交由init进程管理,其他进程不能直接修改属性,而只能通知init进程来修改,而在这过程中,init进程可以进行权限控制,我们来看看具体的流程是什么。


6.1 property_init

代码路径:platform/system/core/property_service.cpp

作用:初始化属性系统,并从指定文件读取属性,并进行SELinux注册,进行属性权限控制

清除缓存,这里主要是清除几个链表以及在内存中的映射,新建property_filename目录,这个目录的值为 /dev/_properties_

然后就是调用CreateSerializedPropertyInfo加载一些系统属性的类别信息,最后将加载的链表写入文件并映射到内存

27cc8a1ddc3835553beabac7ff40dcf8.png

通过CreateSerializedPropertyInfo 来加载以下目录的contexts:

1)与SELinux相关

/system/etc/selinux/plat_property_contexts/vendor/etc/selinux/vendor_property_contexts/vendor/etc/selinux/nonplat_property_contexts/product/etc/selinux/product_property_contexts/odm/etc/selinux/odm_property_contexts

2)与SELinux无关

/plat_property_contexts/vendor_property_contexts/nonplat_property_contexts/product_property_contexts/odm_property_contexts

6.2 StartPropertyService

代码路径:platform/system/core/init.cpp

作用:启动属性服务

首先创建一个socket并返回文件描述符,然后设置最大并发数为8,其他进程可以通过这个socket通知init进程修改系统属性,

最后注册epoll事件,也就是当监听到property_set_fd改变时调用handle_property_set_fd

b88825cd8f2b50d82125494632ed1781.png

6.3 handle_property_set_fd

代码路径:platform/system/core/property_service.cpp

作用:建立socket连接,然后从socket中读取操作信息,根据不同的操作类型,调用HandlePropertySet做具体的操作

HandlePropertySet是最终的处理函数,以"ctl"开头的key就做一些Service的Start,Stop,Restart操作,其他的就是调用property_set进行属性设置,不管是前者还是后者,都要进行SELinux安全性检查,只有该进程有操作权限才能执行相应操作。

0e5e0f4cea7dbc0b074aca00acea3abc.png
6677ec796ccdc1e398519822b03d05d6.png

7.第三阶段init.rc

当属性服务建立完成后,init的自身功能基本就告一段落,接下来需要来启动其他的进程。但是init进程如何其他其他进程呢?其他进程都是一个二进制文件,我们可以直接通过exec的命令方式来启动,例如 ./system/bin/init second_stage,来启动init进程的第二阶段。但是Android系统有那么多的Native进程,如果都通过传exec在代码中一个个的来执行进程,那无疑是一个灾难性的设计。

在这个基础上Android推出了一个init.rc的机制,即类似通过读取配置文件的方式,来启动不同的进程。接下来我们就来看看init.rc是如何工作的。

init.rc是一个配置文件,内部由Android初始化语言编写(Android Init Language)编写的脚本。

init.rc在手机的目录:./init.rc

init.rc主要包含五种类型语句:

  • Action
  • Command
  • Service
  • Option
  • Import
0989744fd523d0b64c5b5458ce05517b.png

7.1 Action

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

Action: 通过触发器trigger,即以on开头的语句来决定执行相应的service的时机,具体有如下时机:

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

7.2 Command

command是action的命令列表中的命令,或者是service中的选项 onrestart 的参数命令,命令将在所属事件发生时被一个个地执行.

下面列举常用的命令

  • class_start : 启动属于同一个class的所有服务;
  • class_stop : 停止指定类的服务
  • start : 启动指定的服务,若已启动则跳过;
  • stop : 停止正在运行的服务
  • setprop :设置属性值
  • mkdir :创建指定目录
  • symlink : 创建连接到的符号链接;
  • write : 向文件path中写入字符串;
  • exec: fork并执行,会阻塞init进程直到程序完毕;
  • exprot :设定环境变量;
  • loglevel :设置log级别
  • hostname :设置主机名
  • import :导入一个额外的init配置文件

7.3 Service

服务Service,以 service开头,由init进程启动,一般运行在init的一个子进程,所以启动service前需要判断对应的可执行文件是否存在。

命令:

service [ ]*

224e6597e7ceca960a8912796972e79f.png

init生成的子进程,定义在rc文件,其中每一个service在启动时会通过fork方式生成子进程。

例如: service servicemanager /system/bin/servicemanager代表的是服务名为servicemanager,服务执行的路径为/system/bin/servicemanager。


7.4 Options

Options是Service的可选项,与service配合使用

  • disabled: 不随class自动启动,只有根据service名才启动;
  • oneshot: service退出后不再重启;
  • user/group: 设置执行服务的用户/用户组,默认都是root;
  • class:设置所属的类名,当所属类启动/退出时,服务也启动/停止,默认为default;
  • onrestart:当服务重启时执行相应命令;
  • socket: 创建名为/dev/socket/的socket
  • critical: 在规定时间内该service不断重启,则系统会重启并进入恢复模式

default: 意味着disabled=false,oneshot=false,critical=false。


7.5 import

用来导入其他的rc文件

命令:

import


7.6 init.rc 解析过程

7.6.1 LoadBootScripts

代码路径:platformsystemcoreinitinit.cpp

作用:如果没有特殊配置ro.boot.init_rc,则解析./init.rc

把/system/etc/init,/product/etc/init,/product_services/etc/init,/odm/etc/init,

/vendor/etc/init 这几个路径加入init.rc之后解析的路径,在init.rc解析完成后,解析这些目录里的rc文件。

400f25a97d89de4f64fda07f5bf1f28a.png

Android7.0后,init.rc进行了拆分,每个服务都有自己的rc文件,他们基本上都被加载到/system/etc/init,/vendor/etc/init, /odm/etc/init等目录,等init.rc解析完成后,会来解析这些目录中的rc文件,用来执行相关的动作。

代码路径:platformsystemcoreinitinit.cpp

作用:创建Parser解析对象,例如service、on、import对象

1f8cb5731d8cff4801ee5cf265b7bd7b.png

7.6.2 执行Action动作

按顺序把相关Action加入触发器队列,按顺序为 early-init -> init -> late-init. 然后在循环中,执行所有触发器队列中Action带Command的执行函数。

d0d801c6c8421c8947ba569a86b1b0f0.png

7.6.2 Zygote启动

从Android 5.0的版本开始,Android支持64位的编译,因此zygote本身也支持32位和64位。通过属性ro.zygote来控制不同版本的zygote进程启动。

在init.rc的import段我们看到如下代码:

import /init.${ro.zygote}.rc // 可以看出init.rc不再直接引入一个固定的文件,而是根据属性ro.zygote的内容来引入不同的文件

init.rc位于/system/core/rootdir下。在这个路径下还包括四个关于zygote的rc文件。

分别是

init.zygote32.rc,

init.zygote32_64.rc,

init.zygote64.rc,

init.zygote64_32.rc,由硬件决定调用哪个文件。

这里拿64位处理器为例,init.zygote64.rc的代码如下所示:

fef4d11759dda7cc6e5c775ac6066d29.png
service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server 解析:service zygote :init.zygote64.rc 中定义了一个zygote服务。init进程就是通过这个service名称来创建zygote进程/system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server解析:zygote这个服务,通过执行进行/system/bin/app_process64 并传入4个参数进行运行:参数1:-Xzygote 该参数将作为虚拟机启动时所需的参数参数2:/system/bin代表虚拟机程序所在目录参数3:--zygote指明以ZygoteInit.java类中的main函数作为虚拟机执行入口参数4:--start-system-server告诉Zygote进程启动systemServer进程

8.总结

init进程第一阶段做的主要工作是挂载分区,创建设备节点和一些关键目录,初始化日志输出系统,启用SELinux安全策略。

init进程第二阶段主要工作是初始化属性系统,解析SELinux的匹配规则,处理子进程终止信号,启动系统属性服务,可以说每一项都很关键,如果说第一阶段是为属性系统,SELinux做准备,那么第二阶段就是真正去把这些功能落实。

init进行第三阶段主要是解析init.rc 来启动其他进程,进入无限循环,进行子进程实时监控。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值