Android Kernel基于Linux Long Term Supported(LTS) kernel,并在此基础上添加了很多Android定制的Patch,形成了Android Common Kernels(ACKs)。

5.10及以上版本的ACK也被称为Generic kernel images(GKI) kernel。

GKI内核聚合了硬件无关的通用核心代码以及GKI模块,与Vendor模块分隔开来。

GKI为Vendor模块提供的接口,借助Kernel Module Interface(KMI)完成,KMI包含了一系列Vendor模块所需的函数和全局数据符号组成。

GKI kernel and vendor module architecture

KMI的作用

ABI工具:https://android.googlesource.com/kernel/build/+/refs/heads/main-kernel/abi/

一直以来,Linux Kernel对主线内核维护一套稳定内核ABI的想法不屑一顾,因为面临不同的工具链、内核配置和快速发展的Linux主线内核,要在主线中保持稳定的ABI是非常困难的。

而Google为了解决Kernel碎片化引起的兼容性与安全性问题,就必须在GKI的基础之上,提供一个稳定的KMI给芯片、供应商(Vendor)开发自己的内核模块,提供独有的系统能力。

注意:KMI是ABI的一个子集,KMI定义的符号,用于Vendor内核模块的开发。此外ABI符号列表最终被编译到二进制stgKMI符号以文本形式放到文件中

Google通过以下方式来提供稳定的KMI:

  • 内核使用通用的Config(gki_defconfig)来进行GKI内核构建,这样核心内核函数以及全局数据结构的符号数量将会固定下来。
  • KMI仅在同一LTS内核版本以及同一Android版本保持稳定。一旦Android版本或LTS内核版本有一个发生变化,都不保证KMI稳定性。
  • AOSP自身提供特定版本的Clang工具链用于构建内核和内核模块。
  • 强制Vendor模块必须使用KMI符号列表中的符号开发内核模块,如果发现使用非KMI符号,将会在运行时加载失败。
  • 一旦KMI分支冻结,修改内核时无法再修改KMI符号列表中的符号定义,一旦改变将构建失败,并进行提示。

如何扩展KMI符号

https://source.android.com/docs/core/architecture/kernel/howto-symbol-lists

  1. 修改GKI内核功能

    1. 在KMI冻结之前,可以修改内核函数、数据结构,并通过Update the reference ABI representation流程更新ABI和KMI符号列表。修改需要提交给ACK,审批通过后生效。
    2. 在KMI冻结之后,依旧可以修改内核函数、数据结构,但是不能影响之前冻结的ABI。修改需要提交给ACK,审批通过后生效。
  2. 在GKI添加桩函数。修改需要提交给ACK,审批通过后生效。

  3. 在KMI增加已有的符号。修改需要提交给ACK,审批通过后生效。

如何确保Vendor模块和KMI、GKI兼容

使用目标ACK代码来开发内核或模块,将内核、ABI、KMI改动同步到ACK,并将开发完成的代码迁移回Byte的代码库。(如果项目Vendor部分已经和ACK进行或者有计划进行同步,可以直接用项目Vendor代码开发内核模块和内核功能)