Android 启动流程分析
首先,需要建立一个概念,Android 启动,本质上是一个逐层接力的过程:
- 第一层,把硬件从"刚上电"带到"可以继续启动"
- 第二层,把系统从"裸硬件"带到"Linux 内核已经运行"
- 第三层,把 Linux 用户空间带到"Android 自己的运行环境建立起来"
- 第四层,把 Android framework 服务带起来
- 第五层,把桌面和应用生态带起来
所以,Android 的启动过程并不是一个单一的动作,而是一条非常长的链。
可以拆分成这样的过程 上电=>BootRom=>BootLoader=>Kernel=>init=>Zygote=>SystemServer=>Launcher/App
BootROM:设备上电后最早执行的代码
当按下电源,设备上电之后,CPU 会读取固化在芯片内部的一小段只读启动代码,这个是 CPU 厂商预先写死的,它主要做一下几件事情:
- 1.给硬件(如内存,时钟)做初始化工作,确保硬件能够正常运行
- 2.从存储设备(如闪存,就是常说的手机存储空间,例如 128GB/256GB,其中存储了 Bootloader,boot 镜像等)中找到并加载 BootLoader 到内存(RAM)中,然后让 CPU 开始执行 BootLoader 代码
他跟我们电脑启动的时候,需要先运行 BIOS,检测硬件后再启动操作系统是一样的流程
Bootloader:把启动流程正式接到操作系统上
当设备的 BootRom 启动之后,设备就要进入 bootloader 阶段了,它主要负责将操作系统加载起来,常见的解 bl 锁就是说的它,接着介绍一下它主要做哪些事情
硬件初始化
Bootloader 的第一步是初始化硬件,它会完成一系列操作来确保硬件设备能够正常工作
- 初始化 CPU 始终,内存控制器:确保 CPU 和内存能够以正确的频率和模式工作
- 设置电源管理和时钟:为设备提供适当的电源时序和时钟信号
- 初始化基本外设: 比如 GPIO,串口,USB,显示等外设的初始化,确保硬件准备好,能够与操作系统进行交互
识别启动模式
Bootloader 负责检查设备的启动模式,通常会有以下几个不同的启动方式:
- 正常启动(Normal Boot): 从正常的启动分区或镜像中加载操作系统
- 恢复模式(Recovery Mode): 进入设备的恢复模式,通常用于刷机或修复系统
- fastboot 模式(Fastboot Mode): 允许通过 fastboot 工具与设备交互,进行刷机等操作
- 下载模式(Download Mode): 某些设备用来连接电脑进行固件升级或重置操作
Bootloader 通过检查硬件的特定信号(例如电源按键,特殊的命令行或引导参数)来决定进入哪个模式
选择启动镜像
Bootloader 会根据硬件的配置、启动模式以及可能传递给它的启动参数,选择合适的启动镜像:
- 选择 boot.img 或其他启动镜像:通常包括内核(Kernel)、文件系统、驱动程序等内容。
- 检查镜像的完整性:现代的 Bootloader 通常会校验镜像的哈希值或签名,确保加载的镜像没有被篡改。
准备内核启动参数
在加载内核之前,Bootloader 会准备一些必要的参数,传递给 Linux 内核:
- 内核启动参数:例如设置根文件系统位置、内存配置、调试模式等。
- 设备树信息(Device Tree):提供关于硬件设备的配置信息,帮助内核正确识别和配置硬件。
加载内核镜像
Bootloader 负责将内核镜像加载到内存中:
- 从存储设备读取内核镜像(比如从闪存读取到 RAM)
- 解压内核镜像(如果是压缩的)
- 加载初始 RAM 磁盘(initrd/initramfs),如果有的话
启动内核
最终,Bootloader 会将控制权交给 Linux 内核:
- 跳转到内核入口点,内核开始执行。
- 将内核的启动参数、设备树信息传递给内核,确保内核能够顺利启动。
切换到 Linux Kernel
一旦 Bootloader 完成上述所有任务,它会将 CPU 控制权交给 Linux 内核,然后退出。此时,内核开始加载并接管设备,之后进入用户空间的初始化阶段。
Kernel:Linux 内核把设备变成一个真正能运行的系统
android 本质上就是一个特殊的 Linux 系统,在这一步自然是将 Linux 内核进行初始化
Kernel 这一阶段的工作非常多,主要涉及系统最基础的资源管理和硬件抽象层的建立。具体来说,Kernel 执行以下几项工作:
- 建立内存管理: 内存是任何操作系统都必须管理的核心资源。Kernel 在此阶段为整个系统建立虚拟内存管理系统,使得程序可以在用户空间和内核空间之间自由运行,而不发生冲突。
- 建立进程和线程基础机制:Kernel 负责建立进程管理和线程调度机制,它为系统上运行的应用程序提供基础的调度能力。进程调度、线程管理、进程隔离等都在 Kernel 阶段完成。通过这一机制,操作系统可以有效分配 CPU 资源,实现多任务并发运行。
- 初始化硬件设备驱动:Android 使用的硬件设备很多,如 CPU、GPU、网络、存储设备等,Kernel 在这一步会加载硬件设备驱动。驱动程序(Driver)使得操作系统能够识别硬件设备,并与硬件进行交互。
- 初始化外设(如输入设备、显示屏等):除了核心硬件,Kernel 还要初始化设备的外围组件,比如触摸屏、按键、LED 灯、显示器等。
- 建立文件系统:在 Kernel 阶段,操作系统还会初始化文件系统,使得设备能够支持数据读写。这通常包括为分区(如 /system、/data)挂载文件系统,让内核能够处理文件操作。
- 准备系统调用接口:系统调用是用户空间与内核空间交互的方式,Kernel 在此阶段为后续的用户空间程序提供操作系统的接口,供程序访问硬件、执行 I/O 等操作。
- 启动系统控制功能:例如在启动过程中,内核会根据启动参数调整硬件的配置(如 CPU 时钟频率、电源管理策略等),确保硬件处于合适的运行状态。
用户空间初始化:启动 init 进程
在完成内核的基本初始化后,内核会进入用户空间,启动 init 进程,它是操作系统的第一个用户空间进程,编号是 PID 1。 init 进程负责整个用户空间的初始化工作。
接着需要来介绍以下这一阶段到底干了哪些事情?
解析 init.rc 配置文件: 这是一个定义 Android 系统启动服务和行为的脚本文件。它描述了系统启动过程中各个服务的执行顺序,定义了哪些进程需要被启动,哪些硬件模块需要初始化等。
启动服务: 根据 init.rc 配置文件,init 进程会启动一系列系统服务,如启动网络服务、权限管理、设备驱动等基础服务。
挂载文件系统:启动进程时,init 会挂载系统需要的文件系统,如 /system、/data、/vendor 等分区,为后续进程提供存储支持。
启动服务
启动 Zygote 进程:Zygote 是 Android 中的进程孵化器,init 会启动 Zygote 进程,然后 Zygote 会负责创建系统中的其他进程,包括应用程序进程。
init 进程是 Android 系统的用户空间起点,它将整个操作系统的服务和功能组织起来,并将硬件和操作系统内核之间的隔离打破,开始启动系统服务。
Zygote 进程:进程的孵化器
首先,Zygote 是 Android 系统中非常重要的一个进程,它是进程孵化器,负责启动后续的应用程序和系统服务。
- Zygote 是由 init 进程启动的,通常在用户空间进入后不久,它就会被拉起。
- 它的作用是预加载一些基础的 Java 类和系统资源,加速后续进程的启动。
Zygote 在这一阶段主要会干以下几件事情:
预加载系统类和资源:Zygote 会预先加载一些常用的类和资源,比如 Android 框架、运行时环境、资源文件等。这样,后面应用程序在启动时,就不需要重复加载这些资源,可以直接使用。
通过 fork() 启动新进程: - 一旦 Zygote 启动,它会通过 fork() 机制派生出新的进程。所有的 Android 应用进程(包括系统进程)都由 Zygote 派生出来。
- Zygote 通过 fork() 加速进程启动,并且能够共享已加载的资源,提高系统的效率。
为什么需要 Zygote 呢?
第一,进程孵化器:每次启动应用时,Zygote 会使用 fork() 复制自己,这样启动应用就能避免每次都从零开始加载资源,极大地提高了效率。
第二,共享资源:通过 Zygote 的 fork(),不同的进程共享同一份资源,避免重复加载,节省内存。
SystemServer 启动服务和管理系统
SystemServer 是 Android 系统中最重要的进程之一,它在 Zygote 启动后开始工作,负责启动和管理多个关键系统服务。
主要任务
启动核心服务:启动 ActivityManagerService (AMS)、PackageManagerService (PMS)、WindowManagerService (WMS) 等系统核心服务。
系统服务的初始化:例如电源管理服务(PowerManagerService)、音频管理服务(AudioService)等。
调用 systemReady():一旦所有系统服务初始化完成,SystemServer 会调用 systemReady() 方法,表示系统进入“完全可用”状态。
启动核心服务
ActivityManagerService (AMS)
AMS 是负责管理 Android 应用的生命周期、任务栈、应用启动等核心服务。它负责管理和调度正在运行的应用,并决定哪个应用应该被激活,哪个应该被暂停或杀死。
PackageManagerService (PMS)
PMS 负责管理安装、卸载和更新应用程序。它是操作系统和应用程序之间的中介,确保应用程序的资源和权限管理符合系统规则。
WindowManagerService (WMS)
WMS 管理应用程序的窗口和显示。它负责处理窗口的创建、显示、移动、大小调整等操作。它与输入事件(如触摸和点击)密切相关,确保用户可以看到和交互应用。
PowerManagerService
PowerManagerService 管理设备的电源状态,控制屏幕亮度、休眠模式等。它确保设备能根据用户设置和系统需求进行电源管理。
执行 systemReady() 方法
当所有的核心服务启动并完成初始化后,SystemServer 会调用 systemReady() 方法。这个方法标志着系统已经准备好,可以提供给应用程序和用户使用了。systemReady() 方法通常会进行一些最后的检查和初始化操作,确保系统在用户交互前已经完全稳定。
Launcher:系统最终进入用户交互阶段
在 Android 启动流程中,Launcher 代表着系统启动的最终可用状态。它标志着所有系统服务已经准备就绪,用户可以开始与设备交互了。
在 SystemServer 完成系统服务的启动后,ActivityManagerService (AMS) 会最终启动 Launcher。具体来说,过程如下:
- SystemServer 启动 AMS:AMS 是负责管理应用生命周期的服务,它在系统启动完成后会启动 Launcher。
- Launcher 被启动:AMS 启动 Launcher 应用并把它显示到屏幕上。这时,用户就可以看到桌面,开始与设备交互。
到这里,Android 启动流程就基本完成了。