로드 가능한 커널 모듈

Android 8.0에 도입된 모듈 커널 요구사항의 일부로 모든 SoC(단일 칩 시스템) 커널은 로드 가능한 커널 모듈을 지원해야 합니다.

커널 구성 옵션

로드 가능한 커널 모듈을 지원하기 위해 모든 일반 커널의 android-base.cfg에는 다음 커널 구성 옵션(또는 상응하는 커널 버전)이 포함됩니다.

CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
CONFIG_MODVERSIONS=y

모든 기기 커널에서 이러한 옵션을 사용 설정해야 합니다. 커널 모듈은 가능한 경우 항상 로드 취소 및 재로드도 지원해야 합니다.

모듈 서명

GKI 공급업체 모듈에는 모듈 서명이 지원되지 않습니다. 자체 검사 부팅을 지원하는 데 필요한 기기에서는 커널 모듈이 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_dlkm/lib/modules의 심볼릭 링크인 /system/lib/modules에서 로드해야 합니다.
  • 전체 Android 또는 충전기 모드에 필요한 SoC 공급업체의 커널 모듈은 /vendor/lib/modules에 있어야 합니다.
  • ODM 파티션이 있는 경우 전체 Android 또는 충전기 모드에 필요한 ODM의 커널 모듈은 /odm/lib/modules에 있어야 합니다. 그렇지 않으면 이러한 모듈은 /vendor/lib/modules에 있어야 합니다.
  • 복구 모드(Recovery mode)에 필요한 SoC 공급업체 및 ODM의 커널 모듈은 /lib/modules의 복구 ramfs에 있어야 합니다.
  • 복구 모드(Recovery mode) 및 전체 Android 모드 또는 충전기 모드에 모두 필요한 커널 모듈은 위에서 설명한 것처럼 복구 rootfs/vendor 또는 /odm 파티션에 모두 있어야 합니다.
  • 복구 모드(Recovery mode)에서 사용되는 커널 모듈은 /vendor/odm에만 있는 모듈에 의존하면 안 됩니다. 이러한 파티션이 복구 모드(Recovery mode)에서 마운트되지 않기 때문입니다.
  • 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/lib/modules(recovery ramfs)에 필수 modules.dep를 생성합니다.

모듈 로드 및 버전 관리

modprobe -a를 호출하여 init.rc*에서 모든 커널 모듈을 한 번에 로드합니다. 이렇게 하면 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(Application Binary Interface)에서 손상을 감지하여 해결 방법을 제공합니다. 이 기능은 커널에서 내보낸 각 기호의 프로토타입에 CRC(주기적 중복 검사) 값을 계산하고 이러한 값을 커널의 일부로 저장합니다. 커널 모듈에서 사용하는 기호의 경우 이러한 값은 커널 모듈에도 저장됩니다. 모듈이 로드될 때 모듈에서 사용되는 기호의 값은 커널의 기호 값와 비교됩니다. 이 두 값이 일치하면 모듈이 로드되고 그렇지 않으면 로드에 실패합니다.

공급업체 이미지와 별도로 커널 이미지를 업데이트하려면 CONFIG_MODVERSIONS를 사용 설정합니다. 이렇게 하면 공급업체 이미지의 기존 커널 모듈과의 호환성을 유지하면서 커널에 마이너한 업데이트(LTS의 버그 수정 등)를 할 수 있습니다. 하지만 CONFIG_MODVERSIONS만으로는 ABI 중단이 해결되지 않습니다. 소스 수정 또는 커널 구성 변경으로 인해 커널의 내보낸 기호 프로토타입이 변경되면 이 기호를 사용하는 커널 모듈과의 호환성이 손상됩니다. 이러한 경우 커널 모듈을 다시 컴파일해야 합니다.

예를 들어 커널의 task_struct 구조(include/linux/sched.h에서 정의됨)에는 커널 구성에 따라 조건부로 포함된 많은 필드가 있습니다. sched_info 필드는 CONFIG_SCHED_INFO가 사용 설정된 경우에만(CONFIG_SCHEDSTATS 또는 CONFIG_TASK_DELAY_ACCT가 사용 설정된 경우 발생함) 존재합니다. 이러한 구성 옵션으로 상태가 변경되면 task_struct 구조의 레이아웃이 변경되고 task_struct를 사용하는 커널에서 내보낸 인터페이스가 모두 변경됩니다(예: kernel/sched/core.cset_cpus_allowed_ptr). 이러한 인터페이스를 사용하는 이전에 컴파일된 커널 모듈과의 호환성이 손상되어 이러한 모듈을 새 커널 구성으로 다시 빌드해야 합니다.

CONFIG_MODVERSIONS에 관한 자세한 내용은 Documentation/kbuild/modules.rst에서 커널 트리 문서를 참고하세요.