0. 前言
本文简单介绍下GKI 相关的知识点,方便更快的了解GKI 概念和架构,如果想要了解细节,还是要看官网并结合实际。
相关术语:
ACK:Android Common Kernel
AOSP:Android Open Source Project
GKI:Generic Kernel Image
KMI:Kernel Module Interface
LTS:Long Term Supported
DLKM:Dynamically loadable kernel module
GSI:Generic System Image
VTS:Vendor Test Suite
CTS:Compatibility Test Suite
1. ACK
Android Common Kernel 的简称,是所有Android 产品内核的基础。供应商内核和设备内核位于 ACK 的下游。供应商通过修改内核源代码并添加设备驱动程序,添加了对 SoC 和外围设备的支持。这些修改内容可能很多,以至于设备上运行的代码中有多达 50% 是树外代码(并非来自上游 Linux 和 AOSP 通用内核)。
因此,一个设备内核有以下几部分组成:
- 上游:来自 kernel.org 的 Linux 内核
- AOSP:AOSP 通用内核的其他 Android 专用补丁程序
- 供应商:供应商提供的 SoC 和外围设备支持以及优化补丁程序
- 原始设备制造商 (OEM)/设备:其他设备驱动程序和自定义项
几乎所有设备都具有自定义内核。这就导致了内核碎片化问题。
2. 碎片化的代价
2.1 安全更新需要耗费大量人力
Android 安全公告 (ASB)中引用的安全补丁程序必须向后移植到每个设备内核中。但是,由于存在内核碎片化问题,向正常使用的 Android 设备传播安全修复的代价非常之高。
2.2很难合并长期支持的更新
长期支持 (LTS) 版本包含安全修复和其他重大问题修复。事实证明,使用最新的 LTS 版本是提供安全修复的最有效方式。我们发现,ASB 报告的内核安全问题中有 90% 都已在保持最新状态的 Pixel 设备上得到修复。
不过,由于设备内核中所有的自定义修改,很难仅将 LTS 修复合并到设备内核中。
2.3妨碍 Android 平台进行版本升级
由于碎片化问题,很难向正常使用的设备添加需要更改内核的 Android 新功能。Android 框架代码必须假设支持的内核版本多达 5 个,并且没有针对新的平台版本进行任何内核更改(Android 10 支持内核版本 3.18、4.4、4.9、4.14 和 4.19;在某些情况下,这些版本自 2017 年 Android 8 发布以来还未添加新功能)。
2.4很难将内核更改贡献回上游 Linux
对内核进行完所有更改后,大多数旗舰设备附带的内核版本已经至少存在 18 个月了。例如,kernel.org
于 2017 年 11 月发布了 4.14 版内核,而首批使用 4.14 版内核的 Android 手机于 2019 年春季才发布。
上游内核发布与产品发布之间的这种长时间延迟导致 Android 社区很难将所需的功能和驱动程序馈送到上游内核中,因此解决碎片化问题并非易事。
3. GKI
GKI通过统一核心内核并将 SoC 和板级支持从核心内核移至可加载模块中,解决了内核碎片化问题。GKI 内核为内核模块提供了稳定的内核模块接口 (KMI),因此模块和内核可以独立进行更新。
GKI 有以下特点:
- GKI 从ACK sources 编译而来;
- GKI 是每个架构和每个 LTS 版本的single-kernel binary 加上关联的可加载模块。(目前只有适用于
android11-5.4
和android12-5.4
的 arm64); - GKI 已经过了关联 ACK 支持的所有 Android 平台版本的测试。在 GKI 内核版本的生命周期内不会发生功能弃用;
- GKI 为给定 LTS 中的驱动程序提供了稳定版 KMI;
- GKI 不包括SoC 专用代码或板卡专用代码;
更新点的ACKs 也称为 GKI kernels,因为它们支持分离硬件无关的通用核心内核代码和硬件无关的GKI 模块。GKI kernel 与特定于硬件的供应商模块交互,这些模块包含芯片上的系统和特定于板的代码。GKI kernel 和供应商模块之间的交互,是通过KMI 来实现的,该接口由标识供应商模块所需的函数和全局数据的符号列表组成。
3. GKI 阶段变化
GKI 是一个复杂的变化,它从Android 11版本中的 v5.4 内核开始,分几个阶段推出。
3.1 GKI 1.0
对于 Android 11 平台版本,为了保证与 Treble 兼容,必须对运行 v5.4 内核的设备进行 GKI 测试。
具备 GKI 兼容性是指设备通过将 GKI 启动映像刷写到boot
分区并将 GSI 系统映像刷写到system
分区来安装通用系统映像 (GSI) 和 GKI 内核,因此通过了 VTS 和 CTS-on-GSI+GKI 测试。设备可以附带不同的产品内核,并且可以使用 GKI 未提供的可加载模块。不过,产品内核和 GKI 内核都必须从相同的vendor_boot
和vendor
分区加载模块。因此,所有产品内核都必须具有相同的二进制内核模块接口 (KMI)。供应商可以扩展产品内核的 KMI,前提是它与 GKI KMI 兼容。GKI 1.0 不要求供应商模块可卸载。
GKI 1.0 的目标
- 当产品内核被 GKI 内核取代时,不在 VTS 或 CTS 中引入性能降低问题。
- 减少 OEM 和供应商为了使 AOSP 通用内核保持最新状态而进行的内核维护工作。
- 无论是升级到新 Android 平台版本的设备还是新发布的设备,都在内核中加入核心 Android 变更。
- 绝不破坏 Android 用户空间。
- 将硬件专用组件作为可加载模块从核心内核中分离出来。
3.2 GKI 2.0
搭载 Android S (2021) 平台版本且使用内核版本 v5.x(5.x 是 2020 年年底被选为 LTS 的内核版本)或更高版本的设备必须附带 GKI 内核。将提供已签名的启动映像,并通过 LTS 和重大问题修复定期对其进行更新。由于 KMI 将保持二进制稳定性,因此无需对供应商映像进行任何更改,即可安装这些启动映像。
GKI 2.0 的目标
- 不为 GKI 引入明显的性能或能效降低问题。
- 使 OEM 无需供应商参与即可提供内核安全修复和问题修复 (LTS)。
- 降低更新设备主要内核版本(例如,将 v5.x 更新为 v5.y)所需的费用。
- 通过按照清晰的升级过程更新内核版本,只为每个架构维护一个 GKI 内核二进制文件。
4. GKI 设计
4.1 ACK KMI kernel 分支
GKI kernels 拥有稳定的KMI。KMI 是通过kernel version 和Android platform release 的唯一标识,因此,branches 可以命名为-
. 例如,Android 11 的5.4 GKI kernel 命名为 android11-5.4。Android 12 有两个GKI kernels,android12-5.4 和 android12-5.10
4.2 Common kernel 层次结构
如图,KMI 分支会经历三个阶段:开发阶段 (dev)、稳定阶段 (stab) 和冻结阶段。
KMI 内核被冻结后,除非发现严重的安全问题,并且在不影响稳定版 KMI 的情况下无法解决该问题,否则不会接受任何 KMI 破坏性更改。分支在其整个生命周期内都将保持冻结状态。
冻结的分支中可以接受问题修复和合作伙伴功能,前提是不破坏现有 KMI。只要不影响构成当前 KMI 的接口,就可以使用新的导出符号扩展 KMI。将新接口添加到 KMI 后,它们会立即进入稳定状态,并且不能被将来的更改破坏。
例如,不允许执行向 KMI 接口所用的结构添加字段的更改,因为这会改变接口定义:
struct foo {int original_field1;int original_field2;int new_field; // Not allowed};int do_foo(struct foo &myarg){do_something(myarg);}EXPORT_SYMBOL_GPL(do_foo);
但可以添加新函数:
struct foo_ext {struct foo orig_foo;int new_field;};int do_foo2(struct foo_ext &myarg){do_something_else(myarg);}EXPORT_SYMBOL_GPL(do_foo2);
参考:
https://source.android.google.cn/devices/architecture/kernel/generic-kernel-image