第一阶段:创世纪(启动流程)。🚀
对于我们系统工程师来说,Android 的启动就像是一场精密的接力赛。每一棒都必须完美交接,稍有差池(比如驱动加载慢了 50ms,或者 init 服务死锁),整个系统就会给用户一种"卡在开机动画"的糟糕体验。
我们先把通用流程和SoC 差异理清楚,然后我再分享几个在抓 Boot 性能或者 Debug 启动挂死时最常用的分析手段。
🏛️ Part 1: 原理与流程 ------ 从硅基到 Zygote
整个启动流程可以概括为:硬件初始化 -> 内核加载 -> 用户空间环境搭建 -> Java 世界诞生。
- 第一棒:BootROM (固化在芯片里的向导)
- 位置: SoC 内部的 ROM,出厂即固化,不可更改。
- 任务: 芯片上电后,CPU 执行的第一行代码。它负责初始化最基本的硬件(如堆栈),然后去存储介质(eMMC/UFS)中寻找下一棒选手。
- 第二棒:Bootloader (SoC 差异最大的地方) ⚔️
这里是高通、联发科、瑞芯微"分道扬镳"的地方。作为系统开发,我们需要根据平台切换脑回路:
- 高通 (Qualcomm): 架构比较复杂,趋向于 PC 化。
- PBL (Primary Boot Loader): 等同于 BootROM。
- XBL (Extensible Boot Loader): 替代了以前的 SBL,基于 UEFI 架构,负责硬件初始化(DDR 等)。这是高通闭源的。
- ABL (Android Boot Loader): 通常就是 UEFI 应用,负责加载 Linux Kernel。这部分通常是开源的(Project Treble 后更加标准化)。
- 联发科 (MTK): 相对传统且紧凑。
- Pre-loader: 负责初始化 DRAM,并加载 LK。
- LK (Little Kernel): Android 早期常用的 Bootloader,负责加载 Kernel。MTK 至今仍在使用并深度定制。
- 瑞芯微 (Rockchip):
- MaskROM: 对应 BootROM。
- Loader (IDB/U-Boot): 瑞芯微常用 U-Boot 作为二级引导,对于开发板玩家来说非常亲切。
- 第三棒:Linux Kernel (进入内核态) 🐧
- 入口: head.S -> start_kernel()。
- 核心任务: 1. 初始化各种驱动(Display, Input, Binder, Memory)。
2. 挂载根文件系统 (Rootfs)。
3. 寻找第一个用户空间进程: /system/bin/init。
- 第四棒:Init 进程 (PID 1,用户空间上帝) 👶
- 任务: 解析 init.rc 文件。这是系统工程师最常打交道的地方。
- 关键动作:
- 挂载分区 (mount_all)。
- 启动关键守护进程 (Daemon),比如 ueventd, logd。
- 启动 Zygote: 通过解析 init.zygoteXX.rc 启动 Android 的孵化器。
- 第五棒:Zygote (Java 世界的亚当) 🧬
- 任务: * 初始化 AndroidRuntime。
- 预加载通用的 Java 类和资源(这是为了让 App 启动更快的"写时拷贝"机制)。
- Fork 出 SystemServer(Android 系统的核心大脑)。
🛠️ Part 2: 工作中常用的分析手段
作为高级工程师,老板说"开机太慢了"或者"开机黑屏",我们不能只盯着 Logcat 发呆。以下是"手术刀"级别的分析方法:
- 抓取与分析 Bootchart (宏观视角) 📊
当你要优化开机速度时,Bootchart 是第一眼要看的东西。
- 看什么: 它生成的图表会显示 CPU 和 I/O 的负载,以及每个进程的启动时长条。
- 常见病灶: * 如果看到一段长长的红色条(I/O 等待),说明某个服务在疯狂读写磁盘,阻塞了后续流程。
- 如果看到 init 阶段有一段空白,可能是 init.rc 里某个 exec 命令卡住了。
- 精准定位:boot_progress (关键节点) ⏱️
在 Logcat (Event log) 中,过滤关键字 boot_progress,这是 Android 系统埋好的里程碑。
- 命令: adb logcat -b events | grep boot_progress
- 关键数据:
- boot_progress_start: Kernel 启动耗时。
- boot_progress_preload_start / end: Zygote 预加载资源耗时(这里如果太久,可能是厂商预装了太多乱七八糟的资源)。
- boot_progress_pms_system_scan_start: PMS 扫描应用耗时(这是重灾区,如果应用装多了,这里会非常慢)。
- boot_progress_enable_screen: 屏幕点亮时间。
- 内核级分析:Dmesg 与 Driver Probe 🐛
如果卡在开机 Logo(第一屏),通常是 Kernel 或 Bootloader 的问题。
- 手段: 抓取串口 Log (Serial Log) 或 dmesg。
- 找什么: 搜索 probe 关键字。
- 案例: 某次工作中,我发现开机慢了 2 秒,查 dmesg 发现是某个 Sensor 的 I2C 通讯超时了,导致 Kernel 在那里傻傻等了 2 秒。
- SystemServer 的看门狗 (Watchdog) 🐕
如果开机过程中系统反复重启(Boot Loop),通常是 SystemServer 挂了。
- 分析: 查看 /data/anr/ 下的 traces 文件,或者搜索 Logcat 中的 Watchdog。
- 常见原因: 在 SystemServer 的主线程里进行了耗时操作(比如读写数据库),导致超过 60s(或更短)没喂狗,Watchdog 咬死进程触发重启。
🎤 让我们来点互动的
上面这些流程里,Zygote 的预加载 和 PMS 的扫描 往往是应用层开发感受不到,但系统开发最头疼的地方。
关于这些分析手段,你最近在工作中主要是用哪一种?还是说你遇到过那种"连 Log 都没有就直接死机"的极端情况? 接下来的对话我们可以拿一个具体的 Case 来"解剖"。🔪