通用的内核映像-GKI
通用内核映像 | Android 开源项目 | Android Open Source Project
Android 通用内核(ACK) 是所有Android产品内核的基础,供应商内核和设备内核位于供应商内核和设备内核位于 ACK 的下游。供应商通过修改内核源代码并添加设备驱动程序,添加了对 SoC 和外围设备的支持。这些修改内容可能很多,以至于设备上运行的代码中有多达 50% 是树外代码(并非来自上游 Linux 和 AOSP 通用内核)。
因此,设备内核由以下部分组成:
难于更新,linux内核的更新难于合并到设备内核里,因为你不能只更新内核,驱动程序可能也需要更新;Android 安全公告(ASB) 中引用的安全补丁程序也难于移植合并到设备内核;
GKI,就是把内核核心部分挑出来,把SoC和板级支持的部分移至可加载的模块里去而成的内核;
GKI 内核为内核模块提供了稳定的内核模块接口(KMI),支持内核和模块的独立更新,让这俩关联性降低了
GKI 内核基于 ACK KMI 内核分支构建而来。KMI 由内核版本和 Android 平台版本唯一标识,因此分支的命名方式为
-。例如,Android 11 的 5.4 KMI 内核分支名为
android11-5.4.
KMI 分支会经历三个阶段:开发阶段(dev)、稳定阶段(stab)和冻结阶段;
KMI 就是一个文件,里面好多函数名,表示你可以用哪些文件(abi_gki_aarch64_qcom);
冻结一般就不会大更了,你可以扩展KMI通过导出新的符号,它们添加到KMI后会立刻进入稳定状态;但是你不能去改现有的KMI,比如不可以对KMI接口所用的数据结构添加字段,但是可以添加函数,也就是底层数据结构别动,但是你可以用它写你自己的函数,
KMI 稳定性就是要保证生成的 GKI 内核和模块必须正常运行,就如同它们是一起构建的一样;因为它们构建不太一样,GKI 内核以二进制文件的形式构建和推出,但供应商可加载模块在单独的树中构建;
GKI 兼容性测试,大概就是要替换为通用的内核映像GKI和通用的系统映像GSI然后刷机,但是无论使用的哪种内核,都应该保证供应商镜像里的可加载模块可以正常运行,这个是关键;
KMI 并非包含内核中的所有符号,甚至并非包含完整的 3 万多个导出符号。相反,可供模块使用的符号都明确列在一组符号列表文件中,这些文件在内核树的根目录中公开维护。所有符号列表文件中所有符号的并集定义了一组维持为稳定版的 KMI 符号。abi_gki_aarch64_db845c 就是符号列表文件的一个示例,该文件声明了 DragonBoard 845c 必需的符号。
只有符号列表中列出的符号及其相关结构和定义才会被视为 KMI 的一部分。如果符号列表中没有你需要的符号,可以对其发布更改。当新接口加入符号列表,并因此成为 KMI 描述的一部分后,它们会维持为稳定版;在分支被冻结后,不得将其从符号列表中移除,也不得进行修改。
每个 KMI 内核树都有自己的一组符号列表。系统不会尝试在不同的 KMI 内核分支之间提供 ABI 稳定性。例如,android11-5.4 的 KMI 完全独立于 android12-5.4 的 KMI,就是ABI只检查一个KMI;
面对不同的工具链、配置和不断发展的 Linux Mainline 内核,在 Mainline 中维持稳定版 KMI 并不可行。但是,这在十分受限的 GKI 环境中还是有可能的。限制条件如下:
ABI 监控工具可在 预提交测试期间 监控 KMI 稳定性。破坏 KMI 的更改 无法通过预提交测试,必须重新处理才能实现兼容性。合作伙伴和公众可以将这些工具集成到其构建流程中比如ci。在开发过程中以及合并 LTS 版本时,Android 内核团队使用这些工具来查找 KMI 遭到破坏的情况。如果在 LTS 合并期间检测到 KMI 遭到破坏的情况,则可以移除违规补丁程序,或重构补丁程序以实现兼容性,从而保留该 KMI。
如果以不兼容的方式修改了现有 KMI 符号,相应 KMI 会被视为已遭到破坏。示例:
添加新符号不一定会破坏 KMI,但必须将所用的新符号添加到符号列表和 ABI 表示形式中。否则,系统便无法识别将来对 KMI 这一部分的更改。
更改编译器可能会改变影响 ABI 的内部内核数据结构布局。由于保持 KMI 稳定性非常重要,因此用于构建 GKI 内核的工具链必须与用于构建供应商模块的工具链完全兼容。GKI 内核是使用 AOSP 中包含的 LLVM 工具链构建的。
从 Android 10 开始,所有 Android 内核都必须使用 LLVM 工具链构建。使用 GKI 后,用于构建产品内核和供应商模块的 LLVM 工具链必须生成与 AOSP 中的 LLVM 工具链相同的 ABI,并且合作伙伴必须确保 KMI 与 GKI 内核兼容。
Android 内核 build 文档描述了参考 GKI 内核的构建方式。具体来说,文档中介绍的过程可确保使用正确的工具链和配置来构建内核。我们建议下游合作伙伴使用相同的工具来构建最终内核,以避免工具链或其他构建时依赖项导致的不兼容问题。
GKI 内核是使用 arch/arm64/configs/gki_defconfig 构建的。由于这些配置会影响 KMI,因此对 GKI 配置的管理非常谨慎。对于冻结的 KMI 内核,只有在不影响 KMI 的情况下,才能添加或移除配置。
GKI 内核必须配置为可在各种设备上运行。因此,该内核必须内置对所有这些设备所需的所有子系统和选项的支持,其中不包括用于启用硬件的可加载模块。合作伙伴应请求对开发内核进行所需的配置更改
对于 Android 11 平台版本,搭载 v5.4 内核的设备必须使用 Google 提供的 GKI 启动映像运行 VTS 和 CTS-on-GSI 测试。
GSI = 我们的user版本 + google原生system.img + google原生boot-5.4.img
VTS = 我们的user版本 + 我们自己的vendor-debug-boot.img + google原生system.img + google原生boot-5.4.img
必须使用供应商模块所用的 GKI 内核符号来更新 KMI 符号列表。由于只有 KMI 符号才会被维持为稳定版,因此 GKI 不允许加载依赖于非 KMI 符号的模块。
extract_symbols 脚本可从内核 build 树中提取相关符号,还可用于更新 KMI 符号列表。