Mô-đun nhân hệ điều hành có thể tải

Nằm trong yêu cầu về hạt nhân của mô-đun được giới thiệu trong Android 8.0, tất cả nhân hệ thống trên chip (SoC) phải hỗ trợ các mô-đun nhân hệ điều hành có thể tải.

Tuỳ chọn cấu hình kernel

Để hỗ trợ các mô-đun nhân hệ điều hành có thể tải, android-base.config trong tất cả các nhân phổ biến bao gồm sau đây là các tuỳ chọn kernel-config (hoặc phiên bản kernel tương đương):

CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
CONFIG_MODVERSIONS=y

Tất cả nhân hệ điều hành của thiết bị phải bật các tuỳ chọn này. Mô-đun hạt nhân cũng nên hỗ trợ huỷ tải và tải lại bất cứ khi nào có thể.

Ký mô-đun

Tính năng ký mô-đun không được hỗ trợ cho các mô-đun của nhà cung cấp GKI. Trên những thiết bị được yêu cầu để hỗ trợ xác minh quy trình khởi động, Android yêu cầu các mô-đun nhân phải nằm trong phân vùng đã bật dm-verity. Thao tác này giúp bạn không cần phải ký tài khoản cá nhân các mô-đun để đảm bảo tính xác thực. Android 13 ra mắt khái niệm về mô-đun GKI. Các mô-đun GKI sử dụng thời gian xây dựng của nhân hệ điều hành cơ sở hạ tầng ký để phân biệt giữa GKI và các mô-đun khác trong thời gian chạy. Các mô-đun chưa có chữ ký được phép tải, miễn là các mô-đun đó chỉ sử dụng những biểu tượng có trên danh sách cho phép hoặc được cung cấp bởi các mô-đun chưa được ký khác. Để tạo điều kiện cho các mô-đun GKI ký trong quá trình tạo bản dựng GKI bằng cặp khoá thời gian xây dựng của nhân, Cấu hình hạt nhân GKI đã bật CONFIG_MODULE_SIG_ALL=y. Để tránh ký các mô-đun không phải GKI trong quá trình tạo bản dựng nhân hệ điều hành của thiết bị, bạn phải thêm # CONFIG_MODULE_SIG_ALL is not set trong cấu hình nhân hệ điều hành của bạn mảnh.

Vị trí tệp

Mặc dù Android 7.x trở xuống không bắt buộc các mô-đun nhân (và bao gồm hỗ trợ cho insmodrmmod), Android 8.x và thì bạn nên sử dụng các mô-đun nhân trong hệ sinh thái. Nội dung sau đây bảng cho thấy khả năng hỗ trợ thiết bị ngoại vi tiềm năng dành riêng cho bo mạch trên ba thiết bị Chế độ khởi động Android.

Chế độ khởi động Bộ nhớ Màn hình Bàn phím Pin PMIC Màn hình cảm ứng NFC, Wi-Fi,
Bluetooth
Cảm biến Camera
Khôi phục
Bộ sạc
Android

Ngoài khả năng sử dụng trong các chế độ khởi động của Android, các mô-đun nhân cũng có thể được phân loại theo người sở hữu chúng (nhà cung cấp SoC hoặc ODM). Nếu mô-đun nhân đang được sử dụng, yêu cầu về vị trí của chúng trong hệ thống tệp là như sau:

  • Tất cả nhân hệ điều hành đều phải tích hợp sẵn tính năng hỗ trợ khởi động và gắn kết phân vùng.
  • Các mô-đun hạt nhân phải được tải từ phân vùng chỉ đọc.
  • Đối với các thiết bị bắt buộc phải xác minh quy trình khởi động, các mô-đun nhân phải được được tải từ các phân vùng đã xác minh.
  • Không được đặt các mô-đun hạt nhân trong /system.
  • Các mô-đun GKI bắt buộc đối với thiết bị phải được tải từ /system/lib/modules là mối liên kết tượng trưng đến /system_dlkm/lib/modules
  • Các mô-đun hạt nhân từ nhà cung cấp SoC bắt buộc phải có cho phiên bản Android hoặc Bạn nên đặt chế độ bộ sạc ở /vendor/lib/modules.
  • Nếu có phân vùng ODM, các mô-đun nhân từ ODM là bắt buộc cho chế độ Android hoặc chế độ Bộ sạc đầy đủ sẽ được đặt trong /odm/lib/modules. Nếu không, các mô-đun này phải được đặt trong /vendor/lib/modules.
  • Các mô-đun hạt nhân của nhà cung cấp SoC và ODM cần có cho tính năng Khôi phục nên được đặt trong ramfs khôi phục tại /lib/modules
  • Cần có mô-đun hạt nhân cho cả chế độ Khôi phục và phiên bản Android đầy đủ hoặc Chế độ bộ sạc phải tồn tại cả trong rootfs khôi phục và phân vùng /vendor hoặc /odm (như mô tả ở trên).
  • Các mô-đun hạt nhân dùng ở chế độ Khôi phục không được phụ thuộc vào các mô-đun nằm trong chỉ trong /vendor hoặc /odm, vì những phân vùng đó không gắn kết ở chế độ Khôi phục.
  • Mô-đun nhân của nhà cung cấp SoC không được phụ thuộc vào mô-đun nhân ODM.

Trong Android 7.x trở xuống, /vendor/odm phân vùng không được gắn kết sớm. Trong Android 8.x trở lên, để có thể tải mô-đun từ các phân vùng này, các điều khoản đã được phải gắn các phân vùng sớm cho cả hai các thiết bị không phải A/B và A/B. Việc này cũng đảm bảo các phân vùng được gắn ở cả chế độ Android và chế độ Bộ sạc.

Hỗ trợ hệ thống xây dựng Android

Trong BoardConfig.mk, bản dựng Android sẽ xác định một Biến BOARD_VENDOR_KERNEL_MODULES cung cấp danh sách đầy đủ của mô-đun nhân dành cho hình ảnh nhà cung cấp. Các mô-đun được liệt kê trong biến này được sao chép vào hình ảnh nhà cung cấp tại /lib/modules/, và sau khi được gắn kết trong Android, sẽ xuất hiện trong /vendor/lib/modules (theo các yêu cầu ở trên). Cấu hình mẫu của các mô-đun nhân hệ điều hành của nhà cung cấp:

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

Trong ví dụ này, kho lưu trữ tạo sẵn mô-đun nhân của nhà cung cấp được ánh xạ vào bản dựng Android tại vị trí nêu trên.

Hình ảnh khôi phục có thể chứa một số mô-đun của nhà cung cấp. Hệ điều hành Android Bản dựng xác định biến BOARD_RECOVERY_KERNEL_MODULES cho các mô-đun này. Ví dụ:

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

Bản dựng Android sẽ đảm nhận việc chạy depmod để tạo tệp modules.dep bắt buộc trong /vendor/lib/modules/lib/modules (recovery ramfs).

Tải mô-đun và tạo phiên bản

Tải tất cả các mô-đun nhân trong một lượt truyền từ init.rc* bằng cách gọi modprobe -a Điều này giúp tránh hao tổn tài nguyên khi khởi chạy nhiều lần môi trường thời gian chạy C cho tệp nhị phân modprobe. Chiến lược phát hành đĩa đơn Có thể sửa đổi sự kiện early-init để gọi modprobe:

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

Thông thường, một mô-đun nhân phải được biên dịch với nhân mà mô-đun đó là được sử dụng cùng (nếu không, nhân sẽ từ chối tải mô-đun). CONFIG_MODVERSIONS cung cấp một giải pháp bằng cách phát hiện sự cố trong giao diện nhị phân của ứng dụng (ABI). Tính năng này tính chu kỳ giá trị kiểm tra dự phòng (CRC) cho nguyên mẫu của từng biểu tượng được xuất trong kernel và lưu trữ các giá trị như một phần của kernel; cho các ký hiệu được sử dụng bởi nhân, các giá trị cũng được lưu trữ trong mô-đun nhân. Khi mô-đun sẽ được tải, giá trị của các ký hiệu mà mô-đun sử dụng sẽ được so sánh với các mã trong nhân. Nếu các giá trị này khớp nhau thì mô-đun sẽ được tải; nếu không thì không tải được.

Để cho phép cập nhật hình ảnh hạt nhân tách biệt với hình ảnh nhà cung cấp, bật CONFIG_MODVERSIONS. Làm như vậy cho phép các cập nhật nhỏ đối với nhân hệ điều hành (chẳng hạn như các bản sửa lỗi từ LTS) cần thực hiện trong khi vẫn duy trì khả năng tương thích bằng các mô-đun nhân hiện có trong hình ảnh nhà cung cấp. Tuy nhiên, CONFIG_MODVERSIONS không tự khắc phục sự cố về ABI. Nếu nguyên mẫu của một biểu tượng được xuất trong những thay đổi về hạt nhân, do việc sửa đổi nguồn hoặc do cấu hình hạt nhân thay đổi, điều này phá vỡ khả năng tương thích với các mô-đun nhân sử dụng biểu tượng đó. Trong những trường hợp như vậy, mô-đun nhân phải được biên dịch lại.

Ví dụ: cấu trúc task_struct trong hạt nhân (được định nghĩa trong include/linux/sched.h) chứa nhiều trường theo điều kiện tuỳ thuộc vào cấu hình nhân. sched_info chỉ xuất hiện nếu CONFIG_SCHED_INFO được bật (điều này xảy ra khi CONFIG_SCHEDSTATS hoặc CONFIG_TASK_DELAY_ACCT đã được bật). Nếu các cấu hình này các tuỳ chọn thay đổi trạng thái, bố cục của cấu trúc task_struct các thay đổi và mọi giao diện đã xuất từ nhân hệ điều hành sử dụng task_struct đã được thay đổi (ví dụ: set_cpus_allowed_ptr trong kernel/sched/core.c). Khả năng tương thích với các mô-đun nhân được biên dịch trước đây sử dụng làm hỏng giao diện, buộc các mô-đun đó phải được xây dựng lại bằng nhân hệ điều hành mới .

Để biết thêm thông tin về CONFIG_MODVERSIONS, hãy tham khảo tài liệu trong cây nhân tại Documentation/kbuild/modules.rst