一、启动流程概览:Android系统启动的完整链路

Android系统启动,说白了就是一部「从按下电源键到桌面亮起」的连续剧。我做了这么多年系统优化,每次跟新人聊启动流程,都喜欢先画一条时间线——因为只有知道谁先谁后、谁依赖谁,你才能理解为什么某个阶段会卡住,为什么某个优化手段有效。

今天我们就从头到尾捋一遍这条链路:BootROM → Bootloader → Kernel → Init → Zygote → SystemServer。每个阶段的核心任务是什么?耗时分布长什么样?我会结合我踩过的坑,给你讲清楚。

1.1 整体链路图

先上一张我手绘的流程图。你盯着看30秒,后面再拆开讲,会轻松很多。

Android 系统启动完整链路 BootROM 固化ROM代码 Bootloader 加载boot.img Kernel 驱动+文件系统 Init 解析rc脚本 Zygote 预加载框架 SystemServer 启动系统服务 典型耗时分布(从冷启动到桌面) ~0.5s ~1.5s ~1.0s ~2.0s ~2.5s ~1.5s BootROM+BL Kernel Init Zygote SystemServer Launcher 总耗时约 8~10s(视硬件和优化程度而定)

这张图里,每个阶段我都标了典型的耗时区间。你可能会问:「为什么Zygote和SystemServer占了将近一半的时间?」嗯,这里我先卖个关子,后面会细讲。

1.2 各阶段核心任务拆解

1.2.1 BootROM —— 芯片出厂就写死的「第一行代码」

BootROM 是固化在 SoC 内部 ROM 里的微代码。你没法改它,也没法跳过它。它的任务极其简单:上电后初始化最基本的硬件(时钟、电压、RAM控制器),然后从预定义的存储位置(eMMC/UFS)加载 Bootloader 到 SRAM 中执行

我个人习惯把 BootROM 叫做「系统启动的助跑阶段」。它不干任何复杂的事,但一旦 BootROM 坏了,手机就是一块砖头——这就是所谓的硬砖

💡 小提示: 如果你在做安全启动(Secure Boot),BootROM 里会包含公钥哈希,用于校验 Bootloader 的签名。这个环节一旦被攻破,整个信任链就断了。

1.2.2 Bootloader —— 真正的「看门人」

Bootloader 是运行在 DRAM 中的第一段可编程代码。它通常分两个阶段:

  • 第一阶段(Primary Bootloader, PBL):由 BootROM 加载,初始化 DRAM 控制器,为第二阶段腾出空间。
  • 第二阶段(Secondary Bootloader, SBL):真正的重头戏。它负责加载 boot.img(包含 kernel + ramdisk),校验签名,然后跳转到 kernel 入口。

我记得有一次在某个项目上,Bootloader 阶段花了整整 3 秒。查了半天,发现是显示初始化(Display Init)占了 1.5 秒——厂商在 Bootloader 里做了开机动画。你想想看,开机动画在 Bootloader 阶段播放,用户看到 logo 亮了,但系统其实还没开始跑,这种体验其实挺坑的。

⚠️ 避坑指南: 我曾经遇到过一个 case——Bootloader 里做了太多 USB 外设枚举,导致启动时间暴增。建议 Bootloader 只做最小必要操作:加载 kernel、校验签名、跳转。其他花里胡哨的功能,等 kernel 起来再说。

1.2.3 Kernel —— 操作系统的「地基」

Kernel 启动后,会做以下几件核心的事:

  1. 初始化 CPU 子系统:MMU、中断控制器、定时器。
  2. 驱动初始化:GPIO、I2C、SPI、UART、存储、网络等。
  3. 挂载根文件系统:从 ramdisk 或实际分区挂载 /。
  4. 启动 init 进程:PID 1,用户空间的第一个进程。

这里有个关键点:Kernel 的启动时间很大程度上取决于驱动加载的顺序和方式。比如,如果你的存储驱动是模块化加载(built as module),那就要等文件系统挂载后才能加载——这就形成了死锁。所以,存储驱动必须编译进内核(built-in)。

我见过一个项目,Kernel 阶段花了 2.8 秒,其中 1.2 秒花在了等待某个 I2C 触摸屏驱动 probe 超时上。解决方案?把那个驱动改成异步 probe,或者干脆延迟加载。说白了,Kernel 启动优化就是「能并行的别串行,能延迟的别着急」。

1.2.4 Init —— 用户空间的「大管家」

Init 进程是 Android 用户空间的第一个进程。它的核心工作是解析 init.rc 及其导入的脚本,然后按顺序启动各种服务。

Init 阶段的主要任务包括:

  • 挂载关键分区(system、vendor、data 等)
  • 设置 SELinux 策略(加载 sepolicy)
  • 启动核心服务:ueventd、logd、servicemanager、surfaceflinger 等
  • 最后启动 Zygote
🔑 关键点: Init 阶段的耗时大头往往在 SELinux 策略加载文件系统检查(fsck) 上。我曾经在一个项目上把 SELinux 策略文件从 8MB 压缩到 2MB,Init 阶段直接快了 0.6 秒。

1.2.5 Zygote —— Android 的「进程孵化器」

Zygote 是 Android 框架层的起点。它启动后会做两件大事:

  1. 预加载 Java 框架类:加载所有常用的 Android 框架类(Activity、Service、View 等),大概有 3000+ 个类。
  2. 启动 SystemServer:通过 fork 自身创建 SystemServer 进程。

Zygote 的预加载机制,说白了就是「一次加载,到处使用」。所有 App 启动时都从 Zygote fork 出来,共享已经加载好的类和数据。这样 App 启动就快多了。

但这里有个问题:预加载的类越多,Zygote 启动就越慢。我记得 Android 8.0 之前,Zygote 启动要 3~4 秒。后来 Google 做了优化,把一些不常用的类改成了「按需加载」,才降到了 2 秒左右。

💡 优化思路: 如果你在做系统定制,可以检查一下 preloaded-classes 文件,把那些你确定用不到的类去掉。但小心——删错了会导致 App 启动时 ClassNotFoundException。

1.2.6 SystemServer —— 系统服务的「总指挥部」

SystemServer 是 Android 系统中最重要的进程。它启动后,会依次启动几十个系统服务:

  • 核心服务:ActivityManagerService、WindowManagerService、PackageManagerService
  • 硬件服务:PowerManagerService、BatteryService、SensorService
  • 媒体服务:MediaServer、AudioService
  • 其他:ConnectivityService、LocationManagerService 等

SystemServer 的启动是串行的——每个服务都要等前一个服务初始化完成才能开始。所以,如果某个服务初始化特别慢,整个启动时间就被拉长了。

我遇到过最夸张的一个 case:某个厂商在 PackageManagerService 里扫描所有已安装 App 的签名,耗时 4 秒。后来改成「首次启动全量扫描,后续增量扫描」,直接砍掉了 3 秒。

1.3 耗时分布总结

下面这张表是我基于多个项目经验总结的典型耗时分布。注意,不同硬件和 Android 版本会有差异,但大方向是一致的。

阶段 典型耗时 主要耗时原因 优化空间
BootROM + Bootloader 0.3~0.8s 硬件初始化、签名校验 低(硬件限制)
Kernel 1.0~2.0s 驱动加载、文件系统挂载 中(异步 probe、裁剪驱动)
Init 0.8~1.5s SELinux 加载、fsck、服务启动 高(压缩 sepolicy、并行启动)
Zygote 1.5~2.5s 预加载 Java 类 中(按需加载、精简类列表)
SystemServer 2.0~3.5s 串行启动系统服务 高(并行化、延迟初始化)
Launcher 1.0~2.0s 加载桌面、恢复应用 中(预创建、缓存)

从这张表你可以看到:SystemServer 和 Zygote 是启动优化的主战场,两者加起来占了总耗时的一半以上。Init 阶段虽然时间不长,但优化空间大,也值得关注。

1.4 我的一点经验总结

做启动优化这么多年,我最大的感受是:不要盲目优化,先搞清楚瓶颈在哪。我见过有人花了两周优化 Kernel 启动,结果只快了 0.2 秒——而 SystemServer 里一个服务优化一下就能快 1 秒。

所以,我的建议是:

  1. 先测量,再优化。用 bootchartsystrace 抓出各阶段的精确耗时。
  2. 抓大放小。先解决耗时最长的阶段,别在 0.1 秒的优化上钻牛角尖。
  3. 注意副作用。有些优化(比如延迟加载服务)可能会导致第一次使用该服务时变慢,需要权衡。

好了,启动流程概览就讲到这里。下一节我们会深入 Init 进程,看看它是怎么解析 init.rc 的,以及 SELinux 策略到底是怎么加载的——那才是真正有意思的部分。


公众号:蓝海资料掘金营,微信deep3321