מודולים של ליבה (kernel) שניתן לטעון

כחלק מדרישות הליבה של המודול, שנקבעו ב-Android 8.0, כל ליבות מערכת על שבב (SoC) חייבות לתמוך במודולים של ליבה (kernel) שניתנים לטעינה.

אפשרויות להגדרת ליבה

כדי לתמוך במודולים של ליבה (kernel) שניתנים לטעינה, android-base.config בכל הליבות הנפוצות כולל האפשרויות הבאות לתצורת ליבה (kernel) (או לגרסת הליבה שלהן):

CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
CONFIG_MODVERSIONS=y

כל הליבה של המכשיר חייבת להפעיל את האפשרויות האלה. גם מודולי הליבה צריכים תמיכה בפריקה וטעינה מחדש כשהדבר אפשרי.

חתימת מודול

אין תמיכה בחתימת מודולים במודולים של ספקים של GKI. במכשירים שנדרשים כדי תמיכה בהפעלה מאומתת, Android דורש שמודולי ליבה יהיו במחיצות שבהם dm-verity מופעל. הפעולה הזו תבטל את הצורך לחתום על של האותנטיות שלהם. ב-Android 13 הושקה הקונספט של מודולים של GKI. המודולים של GKI משתמשים בזמן ה-build של הליבה כדי להבחין בין GKI למודולים אחרים בזמן ריצה. אפשר לטעון מודולים לא חתומים כל עוד הם כוללים רק סמלים שמופיעים ברשימת ההיתרים או שסופקו על ידי מודולים לא חתומים אחרים. כדי להקל על חתימה על מודולים של GKI במהלך build של GKI באמצעות זוג מפתחות זמן build של הליבה, הגדרת הליבה של GKI מפעילה את CONFIG_MODULE_SIG_ALL=y. כדי להימנע מחתימה על מודולים שאינם של GKI במהלך גרסאות build של ליבה במכשיר, צריך להוסיף # CONFIG_MODULE_SIG_ALL is not set כחלק מהגדרת הליבה של קטעים שונים.

מיקומי הקבצים

למרות ש-Android 7.x ומטה לא מחייב מודולים של ליבה (kernel) (וכולל תמיכה ב-insmod וב-rmmod), Android 8.x ו- מומלץ יותר להשתמש במודולים של ליבה (kernel) בסביבה העסקית. הבאים טבלה שמציגה תמיכה בציוד היקפי פוטנציאלי ספציפי ללוח עבור שלושה מצבי הפעלה של Android.

מצב הפעלה אחסון מסך לוח חיוג סוללה PMIC מסך מגע NFC, Wi-Fi,
Bluetooth
חיישנים מצלמה
התאוששות
מטען
Android

בנוסף לזמינות במצבי ההפעלה של Android, יכולים להיות גם מודולים של ליבה (kernel) קטגוריות לפי הבעלים שלהן (ספק ה-SoC או ה-ODM). אם מודולים של ליבה נעשה בהם שימוש, הדרישות למיקום שלהם במערכת הקבצים הן ככה:

  • כל הליבה צריכה לכלול תמיכה מובנית באתחול וטעינה מחיצות.
  • צריך לטעון מודולי ליבה ממחיצה לקריאה בלבד.
  • במכשירים שנדרשת בהם הפעלה מאומתת, מודולי הליבה צריכים להיות נטען ממחיצות מאומתות.
  • מודולים של ליבה לא אמורים להיות ממוקמים ב-/system.
  • צריך לטעון את המודולים של GKI מהמכשיר מ: /system/lib/modules שהוא קישור סימבולי /system_dlkm/lib/modules.
  • מודולי ליבה מספק ה-SoC שנדרשים לכל גרסה של Android או מצבי המטען צריכים להיות ב/vendor/lib/modules.
  • אם קיימת מחיצת ODM, מודולים של ליבה (kernel) מה-ODM הנדרשים עבור מצב מלא של Android או 'מטען', יש למקם את /odm/lib/modules אחרת, המודולים האלה אמורים להיות ממוקמים /vendor/lib/modules
  • מודולים של ליבה (kernel) מספק ה-SoC ומ-ODM שנדרשים לצורך שחזור במצב ramfs השחזור צריך להיות /lib/modules.
  • מודולי ליבה נדרשים גם ל'מצב שחזור' וגם ל-Android מלא או מצבי המטען צריכים להיות קיימים גם בrootfs וגם בשחזור /vendor או /odm (כפי שמתואר) שלמעלה).
  • מודולי ליבה שמשמשים במצב שחזור לא יכולים להיות תלויים במודולים רק ב-/vendor או ב-/odm, כי המחיצות האלה לא טעונה במצב שחזור.
  • מודולים של ליבה (kernel) של ספק SoC לא יכולים להיות תלויים במודולים של ליבה (kernel) של ODM.

ב-Android מגרסה 7.x ומטה, /vendor ו-/odm מחיצות לא טוענות מוקדם. ב-Android מגרסה 8.x ואילך, כדי לאפשר טעינת מודול ממחיצות אלה, התנאים נועד לטעון מחיצות מוקדם יותר עבור שניהם מכשירים שהם לא מסוג A/B ו-A/B. גם מבטיח שהמחיצות יהיו טעונות גם במצב Android וגם במצב Charger.

תמיכה במערכת build של Android

ב-BoardConfig.mk, ה-build של 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

בדוגמה הזו, מאגר שנוצר מראש של מודול ליבה של ספק ממופה אל את גרסת ה-build של Android במיקום שצוין למעלה.

תמונת השחזור עשויה להכיל קבוצת משנה של המודולים של הספק. מכשיר Android build מגדיר את המשתנה 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

גרסת ה-build של Android מטפלת בהרצת depmod כדי ליצור את נדרשים modules.dep קבצים ב-/vendor/lib/modules ו-/lib/modules (recovery ramfs).

טעינת מודול וניהול גרסאות

טוענים את כל מודולי הליבה במעבר אחד מ-init.rc* על ידי הפעלה modprobe -a. כך נמנעת התקורה של אתחול חוזר בסביבת זמן הריצה של C לקובץ הבינארי modprobe. אפשר לשנות את האירוע מסוג 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 ...

בדרך כלל, צריך לבצע הידור של מודול ליבה עם הליבה (kernel) של המודול לשימוש בו (אחרת הליבה מסרבת לטעון את המודול). CONFIG_MODVERSIONS מספק פתרון עקיף על ידי זיהוי תקלות בממשק הבינארי של האפליקציה (ABI). התכונה הזו מחשבת ערך מחזורי ערך בדיקת יתירות (CRC) לאב-טיפוס של כל סמל שיוצא הליבה ומאחסנת את הערכים כחלק מהליבה; עבור סמלים שמשמשים את במודול הליבה, הערכים מאוחסנים גם במודול הליבה. כאשר נטען, מתבצעת השוואה בין הערכים של הסמלים ששימשו את המודול לאלה שבליבה. אם הערכים תואמים, המודול נטען; אחרת הטעינה תיכשל.

כדי לאפשר את העדכון של תמונת הליבה בנפרד מקובץ האימג' של הספק: להפעיל את CONFIG_MODVERSIONS. כך אפשר לקבל עדכונים קלים ליבה (kernel) (כמו תיקוני באגים מ-LTS) שצריך לבצע תוך שמירה על תאימות עם מודולי ליבה קיימים בתמונת הספק. אבל, לפעמים CONFIG_MODVERSIONS לא מתקן כשל ב-ABI בעצמו. אם של סמל מיוצא בשינויים בליבה (kernel), בין אם במקור או בגלל שתצורת הליבה (kernel) השתנתה, מפר את התאימות למודולים של ליבה (kernel) שמשתמשים בסמל הזה. במקרים כאלה, צריך לבצע הידור מחדש של מודול הליבה.

לדוגמה, המבנה task_struct בליבה (kernel) (מוגדר באמצעות include/linux/sched.h) מכיל שדות רבים באופן מותנה כלולה בהתאם לתצורת הליבה. sched_info יוצג רק אם האפשרות CONFIG_SCHED_INFO מופעלת ( מתרחש כאשר CONFIG_SCHEDSTATS או CONFIG_TASK_DELAY_ACCT מופעלות). אם ההגדרות האלה המצב של האפשרויות משתנה, הפריסה של המבנה task_struct וכל ממשקים מיוצאים מהליבה (kernel) שמשתמשים task_struct שונו (לדוגמה, set_cpus_allowed_ptr ב-kernel/sched/core.c). תאימות למודולים של ליבה (kernel) שעברו הידור בעבר המשתמשים במודולים האלה הפסקות ממשקים, מה שמחייב את הבנייה מחדש של המודולים האלה באמצעות הליבה (kernel) החדשה. הגדרה אישית.

לפרטים נוספים על CONFIG_MODVERSIONS, בעץ הליבה שבעץ Documentation/kbuild/modules.rst.