1. 内核编译概述:Android内核源码结构、内核版本与GKI、编译环境基本要求
Android 内核编译是嵌入式系统开发和系统定制的基础环节。本章从源码结构、版本演进与编译环境三个维度,帮助开发者建立对 Android 内核编译的整体认知。
1.1 Android 内核源码结构
Android 内核基于 Linux 主线内核,但增加了大量面向移动设备的驱动、框架与安全模块。其源码仓库通常包含以下核心目录:
| 目录/文件 | 说明 |
|---|---|
arch/ |
体系结构相关代码,如 arm64、x86、riscv |
block/ |
块设备 I/O 调度层 |
drivers/ |
设备驱动,包括 Android 特有的 binder、ashmem、ion 等 |
fs/ |
文件系统,如 ext4、f2fs、sdcardfs |
kernel/ |
核心调度、进程管理、锁机制 |
net/ |
网络协议栈,包含 Android 网络过滤与 VPN 支持 |
sound/ |
音频子系统 |
security/ |
SELinux、密钥管理、加密模块 |
android/ |
Android 专用补丁与 GKI 框架层 |
Makefile |
顶层构建入口,定义编译目标与配置 |
提示: 在独立编译内核模块时,最常打交道的目录是
drivers/ 和 include/。模块代码通常放在 drivers/staging/ 或自定义目录中,通过 Kconfig 和 Makefile 接入构建系统。
1.2 内核版本与 GKI(通用内核映像)
Android 内核版本管理经历了从碎片化到统一化的演进。GKI(Generic Kernel Image)是 Google 在 Android 11 之后推行的内核标准化方案,其核心思想是将内核核心与设备驱动解耦。
GKI 带来的关键变化:
- 内核核心统一:所有设备共享同一个内核二进制,Google 负责核心维护。
- 模块化驱动:厂商驱动以可加载模块形式存在,通过
modprobe动态加载。 - ABI 稳定性:GKI 定义了稳定的内核模块接口(KMI),模块跨内核小版本兼容。
- 版本命名:例如
android14-6.1表示 Android 14 基于 Linux 6.1 的 GKI 内核。
注意: 如果你的目标设备是 Android 12 及以上,强烈建议基于 GKI 内核进行模块开发。非 GKI 内核(如 Android 10 及更早)的模块编译方式差异较大,需要额外处理板级头文件。
1.3 编译环境基本要求
独立编译 Android 内核模块需要一套精简但完整的工具链与环境配置。以下是核心要求清单:
| 组件 | 要求 | 说明 |
|---|---|---|
| 操作系统 | Ubuntu 20.04 / 22.04 LTS | 推荐 x86_64 架构,WSL2 也可用 |
| 交叉编译工具链 | Clang/LLVM 14+ 或 GCC arm64 | Google 推荐使用 Clang,可从 AOSP 预编译工具链获取 |
| 内核源码 | 对应设备的内核树 | 从 android.googlesource.com 或厂商仓库克隆 |
| 内核构建配置 | defconfig 或 gki_defconfig |
需与目标设备内核配置一致 |
| 依赖软件包 | build-essential, flex, bison, libssl-dev, libncurses-dev |
用于内核配置与编译的基础工具 |
| Python 3 | 3.8+ | 内核构建脚本依赖 |
环境验证命令:
# 检查工具链版本
clang --version
aarch64-linux-gnu-gcc --version
# 检查内核源码树
ls -la kernel/ # 应包含 Makefile、Kconfig、arch/ 等
# 检查依赖包
dpkg -l | grep -E "build-essential|flex|bison|libssl-dev|libncurses-dev"
1.4 编译流程概览
一个典型的内核模块独立编译流程包含以下步骤:
- 准备内核源码树:克隆或解压对应版本的内核源码。
- 配置内核:使用
make defconfig或加载目标设备的.config文件。 - 编译内核核心(可选):生成
vmlinux和模块依赖。 - 编写模块代码:创建
hello.c、Kconfig、Makefile。 - 编译模块:使用
make M=drivers/staging/hello独立编译。 - 部署与测试:将
.ko文件推送到设备,使用insmod加载。
1.5 常见问题与避坑
- 内核版本不匹配:模块必须与目标设备运行的内核版本完全一致,否则
insmod会报Invalid module format。 - 缺少
Module.symvers:如果只编译模块而不先编译内核核心,需要从预编译内核中提取该文件,否则模块可能无法正确链接符号。 - 头文件路径错误:确保
KERNEL_SRC环境变量指向正确的内核源码树,且include/目录包含所有必要的头文件。 - GKI 模块签名:Android 12+ 的 GKI 内核要求模块经过签名才能加载,开发阶段可通过关闭
CONFIG_MODULE_SIG绕过。
最佳实践: 在开始模块开发前,先使用
make kernelrelease 确认内核版本,并用 modinfo 检查目标设备上已有模块的编译参数,确保环境一致。