可載入的核心模組

根據 Android 8.0 所引進的模組核心需求條件。 晶片系統 (SoC) 核心必須支援可載入的核心模組。

核心設定選項

為了支援可載入的核心模組 所有常見核心中的 android-base.config 包含 下列核心設定選項 (或核心版本對等項目):

CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
CONFIG_MODVERSIONS=y

所有裝置核心都必須啟用這些選項。核心模組也應 都支援卸載及重新載入功能

模組簽署

GKI 供應商模組不支援模組簽署。使用的裝置必須符合下列條件: 支援驗證開機程序,Android 要求核心模組必須位於分區 已啟用 dm-verity 的服務如此一來 提供真實性的模組 Android 13 導入了 GKI 模組的概念。GKI 模組使用核心的建構時間 簽署基礎架構,以在執行階段中區分 GKI 和其他模組。 未簽署的模組只要只使用許可清單上的符號,就可以載入 或由其他未簽署的模組提供 如要協助使用核心的建構時間金鑰組在 GKI 建構期間簽署 GKI 模組, GKI 核心設定已啟用 CONFIG_MODULE_SIG_ALL=y。 為避免在裝置核心建構期間簽署非 GKI 模組,您必須將 將 # CONFIG_MODULE_SIG_ALL is not set 做為核心設定的一部分 片段。

檔案位置

雖然 Android 7.x 以下版本並未強制要求核心模組 (且 支援 insmodrmmod)、Android 8.x 和 則更適合在生態系統中使用核心模組。下列 表格列出 Android 啟動模式。

啟動模式 儲存空間 螢幕 撥號鍵盤 電池 PMIC 觸控螢幕 NFC、Wi-Fi、
藍牙
感應器 相機
搶球
充電器
Android

除了 Android 啟動模式的可用性外,核心模組也可能 依擁有者 (SoC 供應商或 ODM) 加以分類。如果核心模組 而對於其在檔案系統中的刊登位置規定, 如下:

  • 所有核心應內建啟動和掛接支援功能 多個分區
  • 核心模組必須從唯讀分區載入。
  • 如果裝置需要驗證開機程序,核心模組應 從已驗證的分區載入。
  • 核心模組不得位於 /system
  • 從下列來源載入裝置所需的 GKI 模組: /system/lib/modules 是以下項目的符號連結: /system_dlkm/lib/modules
  • 提供完整 Android 或最終 Android 版本所需的 SoC 供應商核心模組 充電器模式應位於/vendor/lib/modules
  • 如果有 ODM 分區,則所需的 ODM 核心模組 如要查看完整 Android 或充電器模式,位於 /odm/lib/modules。否則,這些模組應位於 /vendor/lib/modules
  • 復原所需的 SoC 供應商和 ODM 的核心模組 模式的應該位於復原 ramfs/lib/modules
  • 復原模式和完整 Android 都需要核心模組,或是 充電模式 rootfs/vendor/odm 分區 (如 )。
  • 復原模式中使用的核心模組不應依附於模組 僅位於 /vendor/odm,因為這些分區不是 於復原模式下掛接。
  • SoC 供應商核心模組不應依附於 ODM 核心模組。

在 Android 7.x 以下版本中,/vendor/odm 分區不會提前掛接。在 Android 8.x 以上版本中 以便從這些分區載入模組, 及早為 非 A/B 和 A/B 裝置。這也 確保分區在 Android 和充電器模式下均已掛接。

Android 建構系統支援

BoardConfig.mk 中,Android 版本定義了 提供完整清單的 BOARD_VENDOR_KERNEL_MODULES 變數 決定要用於供應商映像檔的核心模組。 這個變數已複製到位於 /lib/modules/ 的供應商映像檔中。 在 Android 中掛接後,會顯示於 /vendor/lib/modules (根據上述規定)。 供應商核心模組的設定範例:

vendor_lkm_dir := device/$(vendor)/lkm-4.x
BOARD_VENDOR_KERNEL_MODULES := \
  $(vendor_lkm_dir)/vendor_module_a.ko \
  $(vendor_lkm_dir)/vendor_module_b.ko \
  $(vendor_lkm_dir)/vendor_module_c.ko

在這個範例中,廠商核心模組預先建構的存放區會對應至 上述位置的 Android 版本。

復原映像檔可能包含供應商模組的子集。Android 會定義 BOARD_RECOVERY_KERNEL_MODULES 的 在這些模組中範例如下:

vendor_lkm_dir := device/$(vendor)/lkm-4.x
BOARD_RECOVERY_KERNEL_MODULES := \
  $(vendor_lkm_dir)/vendor_module_a.ko \
  $(vendor_lkm_dir)/vendor_module_b.ko

Android 版本會負責執行 depmod,以便產生 「/vendor/lib/modules」中需要 modules.dep 個檔案 和 /lib/modules (recovery ramfs)。

模組載入和版本管理

透過叫用,從 init.rc* 的一個傳遞中載入所有核心模組 modprobe -a。這可避免重複初始化的負擔 modprobe 二進位檔的 C 執行階段環境。 early-init事件可修改為叫用 modprobe

on early-init
    exec u:r:vendor_modprobe:s0 -- /vendor/bin/modprobe -a -d \
        /vendor/lib/modules module_a module_b module_c ...

通常,核心模組必須使用模組 搭配使用 (否則核心會拒絕載入模組)。 CONFIG_MODVERSIONS 可偵測故障情形,提供解決方法 應用程式二進位檔介面 (ABI) 中執行。此功能會計算 針對事件中各匯出符號的原型,使用備援檢查 (CRC) 值 並將值儲存為核心的一部分;代表 則這些值也會儲存在核心模組中。當 系統會在載入模組後比較各個模組使用的符號值 與核心中的原始碼相對應如果值相符,系統就會載入模組; 否則載入失敗

如要啟用與廠商映像檔分開更新核心映像檔的功能, 啟用CONFIG_MODVERSIONS。這麼一來,即可對容器進行小幅更新 核心 (例如 LTS 的錯誤修正) 而要維持相容性 與供應商映像檔中現有的核心模組搭配使用。不過 CONFIG_MODVERSIONS 不會自行修正 ABI 中斷的問題。如果 核心變更中匯出符號的原型,可能的原因包括 或是核心設定有所變更,因此這會導致 破壞與使用該符號的核心模組的相容性。此時 就必須重新編譯核心模組。

例如,核心中的 task_struct 結構 (定義於 include/linux/sched.h) 包含許多欄位 (有條件) 所具備的叢集會因核心設定而異sched_info 只有在 CONFIG_SCHED_INFO 啟用時 ( 會發生在CONFIG_SCHEDSTATSCONFIG_TASK_DELAY_ACCT已啟用)。如果這些設定 選項變更狀態,task_struct 結構的版面配置 以及從使用 task_struct 經過修改 (例如 位於「kernel/sched/core.c」的「set_cpus_allowed_ptr」)。 與先前編譯的核心模組的相容性 介面無法運作,必須使用新核心重新建構這些模組 此外還會從 0 自動調整資源配置 您完全不必調整資源調度設定

如要進一步瞭解 CONFIG_MODVERSIONS,請參閱 說明文件,位於 Documentation/kbuild/modules.rst