Android Init进程

一、init介绍

init进程是Linux系统中用户空间的第一个进程,进程号固定为1。Kernel启动后,在用户空间启动init进程,并调用init中的main()方法执行init进程的职责。对于init进程的功能分为4部分:

  • 解析并运行所有的init.rc相关文件

  • 根据rc文件,生成相应的设备驱动节点

  • 处理子进程的终止(signal方式)

  • 提供属性服务的功能

init相关的文件包括如下几个:

文件描述

system/core/init/main.cpp

init进程的入口,只有一个main函数,调用ueventd_main创建设备节点文件,调用FirstStageMain执行init的第1阶段。

system/core/init/ueventd.cpp

创建设备节点文件

system/core/init/first_stage_main.cpp

创建和挂载基本的文件系统,挂载特定分区,启用log

system/core/init/first_stage_init.cpp

system/core/init/selinux.cpp

启动SElinux

system/core/init/init.cpp

SecondStageMain入口,init的第2阶段。

frameworks/base/cmds/app_process/app_main.c

启动了zygote,并且携带参数启动了systemServer

1、kernel_init启动了init进程,init进程属于一个守护进程,准确的说,它是Linux系统中用户控制的第一个进程,它的进程号为1。它的生命周期贯穿整个Linux内核运行的始终。Android中所有其它的进程共同的鼻祖均为init进程。

2、在main函数中会调用ueventd_main函数,ueventd的作用是创建设备节点文件。

Android根文件系统的镜像中不存在“/dev”目录,该目录是init进程启动后动态创建的。

因此,建立Android中设备节点文件的重任,也落在了init进程身上。为此,init进程创建子进程ueventd,并将创建设备节点文件的工作托付给ueventd。

ueventd通过两种方式创建设备节点文件。

第一种方式对应“冷插拔”(Cold Plug),即以预先定义的设备信息为基础,当ueventd启动后,统一创建设备节点文件。这一类设备节点文件也被称为静态节点文件。

第二种方式对应“热插拔”(Hot Plug),即在系统运行中,当有设备插入USB端口时,ueventd就会接收到这一事件,为插入的设备动态创建设备节点文件。这一类设备节点文件也被称为动态节点文件。

3、在main函数中调用ueventd_main函数后会继续调用FirstStageMain。

主要创建和挂载基本的文件系统,挂载特定分区,启用log等。

其中挂载的文件系统是最基本的文件系统,该文件系统是运行于RAM上的,优点是相比disk磁盘来说运行速度快,不占存储空间,特点是易失性,断电即丢失,挂载上最基本的文件系统后会根据根目录"/"来挂载/mnt/{vendor,product}等重要的分区,其他不重要的文件挂载在第二阶段rc中处理,生成 /second_stage_resources/system/etc/ramdisk/build.prop,该文件会在第二阶段使用,在第一阶段并开启kernel log,挂载/first_stage_ramdisk新的根目录,根据设备树(fstab)来创建逻辑分区system,system_ext,vendor,product并挂载到/first_stage_ramdisk根目录上,然后将old 根目录切换到/first_stage_ramdisk 根目录,释放old根目录,/first_stage_ramdisk根目录将赋予较为安全的权限,创建AVB数据校验,启用overlayfs机制来保护分区原子性,初始化恢复模式下的AVB校验方案,然后重新回到main.cpp

4、在FirstStageMain的最后会设置args为selinux_setup,调用execv后又重新执行回到main.cpp中,之后会执行SetupSelinux,启动SElinux

SeLinux 全称 Security-Enhanced Linux 即安全增强型 Linux,基于MAC机制的一种实现,它是一个 Linux 内核模块,也是 Linux 的一个安全子系统,这不是android特有的特性,而是由Linux衍生过来的SEAndroid。

在Android Q版本上就开始推行SeLinux机制且强行执行此机制(沙盒机制,只能获取到AOSP指定的对外的接口去获取),所以在之前很多应用在Android Q上会产生很多权限相关的问题。

5、启动成功SElinux后会进入SecondStageMain

函数实现是在system/core/init/init.cpp中,主要工作如下:

  • 设置init进程优先级并创建/dev/.booting设备块代表init正在初始化执行中。
  • 初始化属性服务,也就是会读取property_contexts文件内容以及读取build.prop内容通过MMAP映射到全局内存中,也就是对所有进程共享该资源。
  • 启动属性服务并创建socket_service,等待新链接去更新或新增属性值。
  • 挂载/apex,vendor_overlay等其他分区。
  • 检查设备是否被unlock解锁。
  • 持续监控/proc/mounts设备文件,解析文件中每一行数据,获取挂载点,挂载分区,文件类型,权限等。将解析内容生成实体类追加到要挂载的mounts_中并进行挂载。
  • 将根目录下所有的目录设置为全局共享,例如对/data设置为根目录下的全局共享。
  • 解析init.rc以及其他import了的rc文件,主要解析rc中的:service,on(action),Import,而zygote进程正是从解析rc文件中创建的,然后根据zygote(本质上就是一个socket),通过JNI调用到上层代码,再fork出systemServer.java。
  • 让init进程无限循环,因为主进程不能退出,退出即代表发生异常。
  • 处理sm(ServiceList)中服务超时重启相关(init.rc中的service),若rc中启动的服务启动超时则会让其服务重新启动。

6、启动zygote

函数实现是在frameworks\base\cmds\app_process\app_main.c中,启动了zygote,并且携带参数启动了systemServer。

二、init启动流程分析

init启动zygote进程的过程

  • 18
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值