内核模块概述

有两种类型的内核模块:与硬件无关的GKI 模块和特定于硬件的供应商模块。此页面提供了两种类型的模块的概述。

GKI模块

通用内核映像 (GKI) 模块用于提供独立于通用核心内核的非启动所需的内核功能。使用 GKI 模块,您可以选择要使用的特定内核功能,通常可以减少内核映像大小和运行时内存消耗。尺寸的减小使 GKI 非常适合 Android Go 设备和其他资源受限的外形规格。

GKI 模块还提供了一种机制,允许供应商在 KMI 冻结里程碑之后合并新的上游功能。如果不构建另一个图像,则无法替换内置代码,而作为模块交付的代码可以由另一个模块替换。

GKI 模块使用内核的构建时签名基础结构在运行时区分 GKI 和其他模块。允许加载未签名模块,只要它们仅使用出现在白名单上或由其他未签名模块提供的符号。

GKI模块有两种逻辑类型: protected GKI moduleunprotected GKI module

受保护的 GKI 模块

受保护的 GKI 模块由 Google 提供,不受任何限制,并且在加载后就像使用内核构建一样。此外,受保护的 GKI 模块具有以下特征:

  • 受保护的 GKI 模块可以访问供应商模块或未受保护的 GKI 模块无法使用的非 KMI 内核符号。
  • 受保护的 GKI 模块可以导出成为 KMI 表面一部分的符号,只要这些符号在符号列表中被引用即可。
  • 受保护的 GKI 模块不能被供应商模块覆盖。

受保护的 GKI 模块是 GKI 模块的默认类别。在 KMI 冻结时,所有 GKI 模块都被认为是受保护的。

未受保护的 GKI 模块

未受保护的 GKI 模块可以被供应商模块覆盖。在 KMI 冻结后,如果 GKI 团队决定供应商需要使用包含来自上游 Linux 的新功能的版本来覆盖默认实现,则受保护的 GKI 模块可能会被重新分类为不受保护。在下一个 GKI 版本中,未受保护的模块在上游代码登陆 Android 通用内核 (ACK) 后被重新分类为受保护。未受保护的 GKI 模块具有以下特点:

  • 未受保护的 GKI 模块与供应商模块具有相同的导出符号访问权限。
  • 未受保护的 GKI 模块无法导出受保护的 GKI 模块导出的符号。
  • 未受保护的 GKI 模块必须保留任何 KMI 接口,就像核心内核的一部分一样。
  • 未受保护的 GKI 模块可以被供应商模块覆盖。

供应商模块

供应商模块由合作伙伴提供,以实现 SoC 和特定于设备的功能。任何未作为 GKI 内核的一部分提供的现有内核模块都可以作为供应商模块提供。

由于 GKI 项目的主要目标之一是尽量减少核心内核中特定于硬件的代码,供应商可以预期 GKI 内核不会包含明确管理自己硬件的模块。例如,供应商 ABC Inc 可以预期,如果没有它们的支持, CONFIG_ABC_SOC_SUPPORT之类的配置将不会作为内置或可加载的 GKI 模块启用。

如果内核驱动程序或框架存在于 ACK 中,但未作为 GKI 内核的一部分提供,供应商可以修改驱动程序并将其作为供应商模块提供。不鼓励对非特定于供应商的模块进行此类修改,因为在未来的版本中 GKI 内核可能会提供相同的功能。当 GKI 内核包含供应商模块提供的功能时,供应商模块将不会加载。例如,Android 11 中没有为 GKI 设置CONFIG_GREYBUS ,因此供应商可能会提供 greybus 供应商模块。但是, CONFIG_GREYBUS可能作为 GKI 内置模块或 Android 12 中的模块启用,在这种情况下,不会加载 greybus 供应商模块。最佳做法是使用非供应商特定驱动程序的上游版本(如果它们作为供应商模块交付)。

您可以在vendorvendor_boot映像中提供供应商模块。引导过程早期所需的模块必须在vendor_boot中。从vendor_boot加载模块会产生启动时间成本。