配套视频:
你知道 Android 手机开机过程有多复杂吗?短短数秒钟的背后,是无数工程师 996 加班的深夜。 本视频从大体上介绍 Android 系统启动的每一个阶段。
1. Boot ROM
当我们按下开机键,系统通电后,cpu 会从固定的一个地址取指令并执行,这个固定的地址通常指向 Boot Rom. Boot ROM 是硬编码在 CPU 内部固定地址的一段 ROM,这块代码由 CPU 制造商提供。在必要的硬件初始化之后,Boot ROM 开始加载 Bootloader 到 RAM 中,然后 CPU 跳转执行 Bootloader
2. Bootloader
Bootloader 代码与 CPU 芯片的内核结构、具体型号、应用系统的配置及使用的操作系统等因素有关,因此,并没有通用的 bootloader 程序,开发时需要用户根据具体情况进行移植。嵌入式 Linux 系统中常用的 Bootloader 有 armboot、redboot、blob、U-Boot、Bios-lt 等,其中 U-Boot 是当前比较流行,功能比较强大的 Bootloader,可以支持多种体系结构,但相对也比较复杂。
Bootloader 完成由硬件启动到操作系统启动的过渡,从而为操作系统提供基本的运行环境。Bootloader 的执行过程一般可分为两个阶段:
阶段一的主要工作包括了:
- 设置异常向量
- 设置 CPU 速度,时钟频率以及终端
- 初始化内存控制器
阶段二的主要工作主要有:
- 初始化 Flash 设备
- 初始化系统内存
- 初始化显示、网络等设备
- 将 Kernel 和根文件系统从 falsh 加载到 RAM 中
- 设置 Kernel 启动参数,启动 Kernel
3. kernel
Android 的 kernel 实际上就是 Linux kernel,只是针对移动设备做了一些优化,所以与其它 Linux kernel 的启动方式大同小异。
Kernel 启动过程可分为两个阶段:
阶段一通常使用汇编代码编写,主要工作有
- 硬件环境的检查,主要是 检查内核与当前硬件是否匹配
- 汇编环境到 C 环境的初始化
- 0 号进程上下文的初始化
- 跳转到 C 环境下
阶段一初始化了进程环境,进入阶段二后,程序进入了 0 号进程,0 号进程一般称为 swapper,swapper 进程的主要任务包括了:
- 初始化进程管理、内存管理、文件系统等核心基础模块
- 加载各类驱动
- 查找并启动 init 进程,
- 启动 kthreadd 进程,kthreadd 进程用于启动其他内核进程,是所有内核进程的父进程。
4. init
init 进程是 Linux 系统中用户空间的第一个进程,进程号为 1,我们可以说它是 root 进程或者所有用户态进程的父进程。
init 进程的主要工作包括了:
- 挂载虚拟文件系统:如 /sys、/dev、/proc
- 启动 property 服务
- 启动 SELinux
- 解析执行 init.rc 文件
5. Zygote
在解析执行 init.rc 文件的过程中会启动大量的 native 守护进程 ,这些程序主要有 servicemanager mediaserver zygote 等,其中最重要的进程非 zygote 莫属。
zygote 是 Android 系统最重要的进程之一。后续 Android 中的 App 进程都是由 zygote 进程 fork 出来的。 Zygote 进程中会初始化 java 运行时 AndroidRuntime. 接着通过 AndroidRuntime 执行 ZygoteInit 类的 main 函数,至此,程序就进入 java 环境。
在 ZygoteInit 类的 main 函数会:
- 初始化 Zygote Socket
- 加载 Android Framework 中的 Java 类和 Android 资源到内存中。Android 通过在 zygote 创建的时候加载 Java 类和 Android 资源,当 fork 出子进程后,子进程和父进程共享这些资源,不需要重新加载,加快了应用程序的启动时间。
- 完成资源加载后,接着会启动 SystemServer。
- 最后开启 Zygote Socket 服务,当有启动应用请求到达,fork 生成 App 应用进程。
6. SystemServer
SystemServer 的主要的作用是启动各种系统服务,比如 ActivityManagerService,PackageManagerService,WindowManagerService 以及硬件相关的 Service ,我们平时熟知的各种系统服务其实都是在 SystemServer 进程中启动的,而当我们的应用需要使用各种系统服务的时候其实也是通过与 SystemServer 进程通讯获取各种服务对象的句柄进而执行相应的操作的。在所有的服务启动完成后,会调用各服务的 service.systemReady(...) 来通知各对应的服务,系统已经就绪。
SystemServer 启动完所有的服务后,会调用各个服务的 service.systemReady(...) 方法,在 ActivityManagerService.systemReady() 中会通过一个 CATEGORY_HOME 类型的 Intent 启动 Launcher(这里是 Android 10 的逻辑,不同版本可能有差异)
最后 Launcher 启动,整个启动过程完成。