【全栈第21课】Bootloader→Kernel→init 开机全流程(阶段四实战开篇)
Android 全栈工程师进阶教程 第21课。Bootloader→Kernel→init 开机全流程(阶段四实战开篇)。基于公开 AOSP 知识整理,含原理、可编译示例、常见问题定位。
> 本文是《Android 全栈工程师进阶教程》系列第 21 课。完整 26 课见 GitHub 仓库。
【全栈第21课】Bootloader→Kernel→init 开机全流程(阶段四实战开篇)
0. 这节课你将搞懂什么
从按电源键到看见桌面,中间每一棒发生了什么,以及"开不了机/卡 logo/卡开机动画"分别卡在哪一棒、怎么定位。 学完你能回答:Android 开机经过哪些阶段?我前面学的东西(HAL 的 class hal、SystemServer、bootphase)在开机流程里哪个位置?设备开不了机/卡 logo/卡动画,我该怎么判断卡在哪、去哪查日志?
1. 背景:开机是所有层的总集成
开机流程把你前面学的全部串起来:bootloader 加载 kernel → kernel 跑 init → init 拉起 HAL(L9 的 class hal)和 zygote → SystemServer 启动各服务(L3)→ 桌面起来。
理解开机流程 = 拿到一张"卡在哪一棒"的定位地图。这是处理"开不了机"类问题(高频且严重)的基础。
2. 全局图:完整开机链
① 按电源键 → PMIC 上电 → SoC 内 BootROM(固化在芯片,改不了)
② BootROM → 加载 Bootloader(高通 XBL/ABL,小米有 ABL 定制)
├ 校验镜像签名(AVB / verified boot)
├ 显示开机 logo
└ 选 A/B slot
③ Bootloader → 加载 boot.img(GKI 内核 + ramdisk)→ 跳进 kernel
④ Kernel 启动
├ 解压、初始化内存/调度/built-in 驱动
└ 挂载 ramdisk → 运行 /init(第一个用户态进程,pid 1)
⑤ init(system/core/init)
├ 解析 init.rc
├ 挂载 system/vendor/data 分区
├ 按 class 启动 service(class core → main → hal → late_start) ← L9 HAL 在 class hal
└ 触发 property trigger
⑥ init 启动 zygote(app_process)
⑦ Zygote → fork SystemServer ← L2/L3 的舞台
⑧ SystemServer 三批 + bootphase 启动各服务 ← L3
⑨ AMS 启动 Launcher → BOOT_COMPLETED(L3 phase 1000)
⑩ 看见桌面
3. 前面课在开机流程的位置
| 你学过的 | 在开机哪一步 |
|---|---|
HAL 的 class hal(L9) | 第 ⑤ 步 init 在 hal 阶段拉起 |
| 内核驱动 .ko / modules.load(L13) | 第 ④⑤ 步加载 |
| SystemServer 三批启动(L3) | 第 ⑧ 步 |
| onBootPhase BOOT_COMPLETED(L3) | 第 ⑨ 步 |
| Binder/servicemanager(L1) | servicemanager 在 init 早期(class core)起,⑦⑧ 才能 addService |
4. 前置准备
- 依赖前面所有课(开机是总集成)。
- 本课偏知识地图 + 定位方法,产出文档。
5. 动手:理解"卡在哪一棒"的定位地图(核心)
开机不出问题就一路到桌面;出问题就卡在某一棒。关键是先判断卡在哪一棒,再针对性查。
| 现象 | 卡在哪一棒 | 去哪查 |
|---|---|---|
| 黑屏完全没反应 | ①BootROM/PMIC/电源 | 硬件、电池、上电时序(示波器/万用表) |
| 卡开机 logo 不动 | ②③④ Bootloader/kernel 早期 | fastboot 日志、串口、kernel 早期 panic、/proc/last_kmsg |
| 反复重启卡 logo | kernel panic / verified boot 失败 | ramdump(L24)、AVB 日志 |
| 卡 bootanimation(开机动画)不进桌面 | ⑤⑥⑦⑧ init/zygote/SystemServer | logcat、init 日志、SystemServer 卡哪个服务 |
| 进桌面后又重启 | ⑧⑨ SystemServer 崩 / watchdog | logcat、tombstone、dropbox |
分水岭:logo 之前卡 = bootloader/kernel(底层);logo 之后/动画卡 = init/framework(上层)。 先用这条线把范围砍一半。
6. 看底层:为什么 servicemanager 必须最早起
init.rc 里 service 按 class 分阶段启动:
class core 最早:ueventd(建设备节点)、logd(日志)、servicemanager(L1 黄页)
class main 主要服务
class hal HAL 进程(L9 的 hello-hal 在这)
class late_start 晚启动
servicemanager 在 class core 早早起来,因为后面 SystemServer(第⑧步)要 addService、HAL 要注册,都依赖它。如果 servicemanager 起不来,整个 Binder 体系瘫痪,开不了机。这解释了为什么它的启动顺序这么靠前。
7. 编译 & 运行(观察 + 抓日志)
adb shell getprop | grep -iE "boot|sys.boot" # 开机状态属性(sys.boot_completed=1 表示开机完成)
adb shell dmesg | grep -iE "init|boot" # kernel/init 日志
adb logcat -b all | grep -iE "SystemServer|Boot" # framework 启动日志
adb shell cat /proc/last_kmsg 2>/dev/null # 上次开机的 kernel 日志(查反复重启)
adb shell cat /sys/fs/pstore/console-ramoops-0 # 死机现场(L24)
fastboot getvar current-slot # 当前 A/B slot(在 fastboot 模式)
> 验证状态(诚实):本课为开机流程知识 + 定位方法,无编译产物。命令为标准开机调试命令。
8. 踩坑提醒
- 黑屏 vs 卡 logo 别混:黑屏(完全没反应)多是硬件/电源;卡 logo 是 bootloader/kernel 起来了但走不下去。判断错方向就错。
- logcat 在卡 logo 阶段没用:logcat 是 framework 起来后才有的,卡 logo(framework 还没起)要看 dmesg/串口/last_kmsg。
- 反复重启看上次日志:正在重启抓不到现场,看
/proc/last_kmsg/pstore 是上一次的崩溃记录。 - A/B slot 启动失败回退:一个 slot 启动失败会自动回退另一个,看 current-slot 是不是变了。
9. 常见问题分析与定位(开机实战)
9.1 常见问题清单
- 卡开机 logo(进不去)
- 卡 bootanimation(开机动画转圈不进桌面)
- 反复重启(boot loop)
- 进桌面后几秒又重启
- 开机特别慢
9.2 分析与定位
① 卡 logo — bootloader/kernel 早期。
# 接串口看 bootloader/kernel 早期日志(最直接)
adb reboot bootloader; fastboot getvar all # bootloader 信息(能进 fastboot 说明 bootloader 活)
adb shell cat /proc/last_kmsg # 若能短暂连上,看 kernel 卡哪
- 能进 fastboot 但不进系统 → kernel/ramdisk 问题或 AVB 校验失败;连 fastboot 都进不去 → bootloader/硬件。
② 卡 bootanimation — init/zygote/SystemServer。
adb logcat -b all | grep -iE "SystemServer|zygote|Boot"
adb shell ps -A | grep -iE "system_server|zygote" # 这俩进程起了吗
adb pull /data/anr/ # SystemServer 卡住会被 watchdog 抓 trace
- system_server 没起 → zygote/init 问题;system_server 起了但卡 → 看它卡在哪个服务(traces.txt,接 L3)。
③ boot loop — kernel panic / SystemServer 反复崩。
adb shell cat /sys/fs/pstore/console-ramoops-0 # kernel panic 现场(L24)
adb logcat -b all | grep -iE "FATAL|watchdog|SystemServer.*crash"
- kernel panic → L24 看栈;SystemServer 崩 → logcat 看哪个服务抛异常。
④ 进桌面后重启 — SystemServer 崩或 watchdog 超时。
adb logcat | grep -iE "watchdog|FATAL EXCEPTION.*system_server"
adb pull /data/tombstones/ # native crash
adb pull /data/system/dropbox/ # crash 记录
⑤ 开机慢 — 某服务/HAL 启动耗时。
adb logcat | grep -i "SystemServerTiming" # 各服务启动耗时(L3)
adb shell dmesg | grep -i "initcall" # 内核 init 耗时
9.3 定位决策树
开机出问题
├─ 先判断分水岭:logo 前(bootloader/kernel)还是 logo 后(init/framework)
├─ 黑屏没反应 → ①硬件/电源(示波器/万用表)
├─ 卡 logo → fastboot getvar(bootloader 活吗)+ last_kmsg → kernel/AVB/bootloader
├─ 卡 bootanimation → logcat SystemServer + ps 看 system_server/zygote 起没 + /data/anr
├─ boot loop → pstore/last_kmsg(kernel panic,L24)+ logcat(SystemServer 崩)
├─ 进桌面后重启 → logcat watchdog/FATAL + tombstone + dropbox
└─ 开机慢 → SystemServerTiming(L3)+ dmesg initcall
10. 小结
- 开机链十步:BootROM→Bootloader→kernel→init→zygote→SystemServer→Launcher。
- 前面课的位置:HAL class hal 在 init(⑤),SystemServer 在 ⑧,BOOT_COMPLETED 在 ⑨。
- 分水岭定位:logo 前卡 = bootloader/kernel;logo 后/动画卡 = init/framework。先砍一半范围。
- 卡 logo 看 dmesg/last_kmsg/串口(logcat 还没有);卡动画看 logcat/SystemServer。
- 排查口诀:先判分水岭;卡 logo 查 fastboot+last_kmsg;卡动画查 SystemServer+ps;boot loop 查 pstore。
下节预告
L22:跨层问题定位武器库 —— 系统梳理每一层用什么工具查问题(logcat/dmesg/ftrace/perfetto/ramdump),建立完整的定位工具地图。