2. Android内核与GKI基础
Android 内核并不是一个“独立于 Linux 的全新系统”,而是以 Linux 内核为底座,叠加 Android 特有的补丁、驱动、调度策略与安全机制后形成的产品化内核。理解 Android 内核架构,是理解 GKI、KMI、ABL 与启动流程的前提。本节从内核分层入手,逐步过渡到 GKI 的定义、KMI 的稳定接口意义,以及 bootloader 与内核启动链路。
一、Android 内核架构:Linux 底座 + Android 增强
Android 内核在结构上可分为三层:最底层是标准 Linux 内核核心,包括进程调度、内存管理、文件系统、网络协议栈、设备驱动模型等;中间层是 Android 特有的增强模块,例如 Binder IPC、ashmem、lowmemorykiller、wakelocks、SELinux 强化、dm-verity 等;最上层是面向 SoC 与板级的厂商驱动与配置,例如显示、摄像头、音频、电源管理、存储控制器等。
这种分层带来一个关键矛盾:Linux 内核社区持续演进,Android 与 SoC 厂商又需要大量定制。若每个设备都维护一棵独立内核树,升级与安全补丁维护成本极高。GKI 正是为解决这一矛盾而提出的工程方案。
二、GKI 定义:通用内核镜像与模块化拆分
GKI(Generic Kernel Image)是 Google 定义的“通用内核镜像”。其核心思想是:将内核中与硬件无关、与 Android 平台相关的核心部分编译为一个通用镜像,由 Google 统一维护与升级;而将 SoC 相关、板级相关的驱动从内核镜像中剥离,编译为可加载内核模块(Kernel Module),由厂商以模块形式提供。
这样,同一 GKI 内核镜像可以跨多个设备与 SoC 复用,安全补丁与内核版本升级只需替换 GKI 镜像,厂商模块通过 KMI 与内核交互,从而显著降低碎片化。
三、KMI:内核模块接口的稳定边界
KMI(Kernel Module Interface)是 GKI 中最为关键的工程约束。它定义了 GKI 内核与厂商模块之间允许使用的符号、函数、结构体与常量集合。只要 KMI 保持稳定,厂商模块就可以在不重新编译内核的情况下,与新的 GKI 内核镜像配合工作。
KMI 的稳定性通过 ABI 监控工具保障,常见检查项包括:导出符号列表、符号 CRC、结构体布局、枚举值、函数签名等。若厂商模块使用了未列入 KMI 的内部符号,升级 GKI 时就会面临模块加载失败或运行异常。
# 查看当前内核导出的符号(示例)
adb shell cat /proc/kallsyms | grep -i "binder"
# 检查模块依赖与符号版本
modinfo vendor_display.ko
modprobe --dump-modversions vendor_display.ko
四、ABL 与 bootloader:启动链的第一棒
ABL(Android Bootloader)是高通平台常见的 bootloader 实现,属于 Android 启动链中的关键一环。典型启动流程为:芯片上电后先执行 Boot ROM,加载并校验 XBL(eXtensible Boot Loader),XBL 初始化关键硬件后加载 ABL,ABL 负责解析 boot 分区、校验 boot.img、设置 cmdline,并最终跳转到内核入口。
ABL 的职责包括:读取分区表、加载 boot.img 与 vendor_boot.img、校验镜像签名、传递设备树与内核参数、支持 fastboot 与 recovery 模式等。对于 GKI 设备,ABL 还需要正确加载 vendor_boot 分区中的厂商模块与设备树。
五、内核启动流程:从 boot.img 到 init
内核启动可概括为:bootloader 将内核镜像与设备树加载到内存,跳转到内核入口;内核完成早期初始化、解压、建立页表、初始化调度与内存管理;随后解析 cmdline 与设备树,加载内置驱动;接着挂载 initramfs,执行 /init;init 再根据 fstab 挂载 system、vendor 等分区,启动 Android 用户空间。
在 GKI 方案中,boot.img 通常包含 GKI 内核与通用 ramdisk,vendor_boot.img 包含厂商模块、设备树与厂商 ramdisk 片段。两者配合完成从内核到 Android 的过渡。
六、案例与场景:GKI 升级中的典型问题
某设备从 Android 13 GKI 升级到 Android 14 GKI 时,厂商显示模块加载失败,日志提示 Unknown symbol。排查发现该模块引用了未列入 KMI 的内部符号 drm_atomic_helper_commit_tail 的私有变体。解决方式是改用 KMI 允许的公开接口,或将该逻辑下沉到 GKI 内核中由 Google 统一维护。
另一个常见场景是 vendor_boot 分区未正确打包设备树,导致内核启动后无法识别屏幕或存储。此时需检查 ABL 是否正确传递 dtb 与 dtbo,以及 vendor_boot.img 的打包脚本是否包含全部模块。
七、关键概念对照清单
| 概念 | 作用 | 交付物/位置 | 升级影响 |
|---|---|---|---|
| GKI | 通用内核镜像,跨设备复用 | boot.img 中的内核 | 可独立升级,需 KMI 兼容 |
| KMI | 稳定模块接口,约束符号与 ABI | 内核导出符号表 | 破坏性变更会导致模块失效 |
| ABL | 校验并加载 boot/vendor_boot | bootloader 分区 | 通常随平台版本更新 |
| vendor_boot | 承载厂商模块与设备树 | vendor_boot.img | 随厂商驱动更新 |
| boot.img | 承载 GKI 内核与通用 ramdisk | boot 分区 | 随 GKI 版本更新 |