2. Android系统架构与内核接口概览
要理解 Android KMI 与 ABI 兼容工程,必须先建立一张“从应用到内核”的完整分层地图。Android 并不是一个从零开始的操作系统,它构建在 Linux 内核之上,又在其上叠加了 Android 特有的运行时、框架与服务。而 GKI、KMI、ABI 这三个概念,正是 Android 在“内核与厂商代码解耦”过程中逐步抽象出来的关键层次。本节将沿着系统架构自下而上,厘清 Linux 内核、Android 通用内核、GKI、KMI、ABI 的基本定义与相互关系。
一、从 Linux 内核到 Android 通用内核
Linux 内核是整个系统的底座,负责进程调度、内存管理、文件系统、网络协议栈、设备驱动、电源管理等最底层能力。它对外提供系统调用(syscall)接口,对上承载所有用户空间程序。传统 Linux 发行版中,内核与驱动、板级支持包(BSP)往往深度耦合,每个设备厂商都会维护一棵自己的内核源码树。
Android 早期沿用了这种模式:每家 SoC 厂商和 OEM 都维护独立的内核分支,导致内核碎片化严重、安全补丁难以统一、升级周期漫长。Android 通用内核(ACK,Android Common Kernel)正是为解决这一问题而出现的。ACK 是在上游 Linux 长期支持版本(LTS)基础上,叠加 Android 特有补丁(如 binder、ashmem、低内存杀手、wakelock、SELinux 增强等)形成的统一内核源码树。所有 Android 设备理论上都应基于同一 ACK 分支开发,从而共享安全修复与功能演进。
二、GKI:通用内核镜像
GKI(Generic Kernel Image,通用内核镜像)是 ACK 的“可启动产物”。它把内核核心与通用驱动编译成一个标准镜像,由 Google 统一发布和维护。GKI 的关键设计是内核模块化:与具体硬件强相关的驱动不再编进内核镜像,而是以可加载模块(.ko)形式存在,由厂商提供并在启动时加载。
这样做的收益非常直接:内核核心可以独立升级,厂商只需维护自己的模块,无需重新编译整棵内核树。GKI 通过 KMI 与厂商模块交互,因此 KMI 的稳定性成为整个机制能否成立的前提。
三、KMI 与 ABI:接口与二进制契约
KMI(Kernel Module Interface,内核模块接口)是 GKI 内核与可加载模块之间的一组符号与接口集合。它规定了哪些内核函数、变量、数据结构可以被模块引用。KMI 是“源码级/符号级”的接口约定。
ABI(Application Binary Interface,应用二进制接口)则更偏向二进制层面的契约:它描述编译后的符号名称、函数签名、结构体布局、对齐方式、调用约定等。对于内核模块而言,ABI 兼容意味着一个针对某 KMI 版本编译的模块,可以在不重新编译的情况下加载到另一个 KMI 兼容的内核上。
四、五层关系总览
下面这张图展示了从应用到硬件的分层结构,以及 GKI、KMI、ABI 在其中的位置。注意:KMI 是 GKI 内核与厂商模块之间的“接口面”,ABI 则是这个接口面在二进制层面的具体表现。
五、核心概念对照表
| 概念 | 全称 | 层次 | 核心作用 | 稳定性要求 |
|---|---|---|---|---|
| Linux 内核 | Linux Kernel | 最底层 | 提供进程、内存、驱动等基础能力 | 上游 LTS 稳定 |
| ACK | Android Common Kernel | 内核源码树 | Linux + Android 补丁的统一内核源码 | 分支内稳定 |
| GKI | Generic Kernel Image | 内核镜像 | 可独立升级的通用内核二进制 | 镜像级稳定 |
| KMI | Kernel Module Interface | 接口层 | 内核与模块之间的符号/接口约定 | 跨版本保持兼容 |
| ABI | Application Binary Interface | 二进制层 | 编译后符号、布局、调用约定的契约 | 二进制级兼容 |
六、典型场景:一次内核升级发生了什么
假设某设备从 GKI 内核版本 A 升级到版本 B。理想流程如下:
- Google 发布新的 GKI 镜像 B,其 KMI 与版本 A 保持兼容。
- 厂商无需重新编译自己的
.ko模块,直接复用原有二进制。 - 系统启动时,GKI 内核加载厂商模块,模块通过 KMI 符号解析成功。
- ABI 校验工具确认模块与内核的符号签名、结构体布局一致。
如果 KMI 发生不兼容变更,模块加载会失败,典型日志如下:
# 模块加载失败示例
insmod: failed to load vendor_display.ko:
Unknown symbol: drm_atomic_helper_commit_tail
disagrees about version of symbol module_layout
# 查看内核符号版本
cat /proc/kallsyms | grep drm_atomic_helper_commit_tail
七、常见误区与复盘
- 误区一:GKI 等于 ACK。ACK 是源码树,GKI 是编译产物。ACK 可以编译出多个 GKI 镜像,GKI 是 ACK 的一种交付形态。
- 误区二:KMI 稳定就等于 ABI 稳定。KMI 是符号级约定,ABI 还涉及结构体布局、对齐、调用约定。符号存在不代表二进制兼容。
- 误区三:所有驱动都必须模块化。GKI 允许部分核心驱动内置,但厂商专有驱动应以模块形式提供,才能享受独立升级收益。
- 误区四:ABI 兼容只靠编译器保证。实际工程中需要 ABI 监控工具、符号列表比对、结构体布局检查等多重手段。