内核模块概览

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

GKI模块

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

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

GKI 模块使用内核的构建时签名基础设施来在运行时区分 GKI 和其他模块。只要未签名的模块仅使用出现在允许列表中或由其他未签名的模块提供的符号,则允许加载未签名的模块。

GKI 模块有两种逻辑类型:受保护的 GKI 模块不受保护的 GKI 模块

受保护的 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 ,因此供应商可能会提供灰总线供应商模块。但是, CONFIG_GREYBUS可能在 Android 12 中作为 GKI 内置或模块启用,在这种情况下,将不会加载灰总线供应商模块。最佳实践是使用非供应商特定驱动程序的上游版本(如果它们作为供应商模块提供)。

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