به عنوان بخشی از الزامات هسته ماژول معرفی شده در Android 8.0، همه هسته های سیستم روی تراشه (SoC) باید از ماژول های هسته قابل بارگیری پشتیبانی کنند.
گزینه های پیکربندی هسته
برای پشتیبانی از ماژولهای کرنل قابل بارگذاری، android-base.config در همه هستههای رایج شامل گزینههای پیکربندی هسته زیر (یا معادل نسخه هسته آنها) است:
CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y CONFIG_MODVERSIONS=y
تمام هسته های دستگاه باید این گزینه ها را فعال کنند. ماژول های کرنل نیز باید در صورت امکان از تخلیه و بارگیری مجدد پشتیبانی کنند.
امضای ماژول
امضای ماژول برای ماژول های فروشنده GKI پشتیبانی نمی شود. در دستگاههای مورد نیاز برای پشتیبانی از بوت تایید شده، اندروید نیاز دارد که ماژولهای هسته در پارتیشنهایی باشند که dm-verity را فعال کردهاند. این امر نیاز به امضای ماژول های جداگانه را برای صحت آنها از بین می برد. اندروید 13 مفهوم ماژول های GKI را معرفی کرد. ماژولهای GKI از زیرساخت امضای زمان ساخت هسته برای تمایز بین GKI و سایر ماژولها در زمان اجرا استفاده میکنند. ماژولهای بدون امضا مجاز به بارگیری هستند تا زمانی که فقط از نمادهایی استفاده کنند که در لیست مجاز ظاهر میشوند یا توسط سایر ماژولهای بدون امضا ارائه شدهاند. برای تسهیل امضای ماژولهای GKI در طول ساخت GKI با استفاده از جفت کلید زمان ساخت هسته، پیکربندی هسته GKI CONFIG_MODULE_SIG_ALL=y
فعال کرده است. برای جلوگیری از امضای ماژولهای غیر GKI در طول ساختهای هسته دستگاه، باید # CONFIG_MODULE_SIG_ALL is not set
اضافه کنید.
مکان های فایل
در حالی که Android 7.x و پایینتر ماژولهای هسته را اجباری نمیکند (و شامل پشتیبانی از insmod
و rmmod
)، Android 8.x و بالاتر استفاده از ماژولهای هسته را در اکوسیستم توصیه میکند. جدول زیر پشتیبانی بالقوه جانبی مخصوص برد مورد نیاز را در سه حالت بوت اندروید نشان می دهد.
حالت بوت | ذخیره سازی | نمایش | صفحه کلید | باتری | PMIC | صفحه لمسی | NFC، Wi-Fi، بلوتوث | حسگرها | دوربین |
---|---|---|---|---|---|---|---|---|---|
بازیابی | |||||||||
شارژر | |||||||||
اندروید |
علاوه بر در دسترس بودن در حالتهای بوت اندروید، ماژولهای هسته ممکن است بر اساس مالک آنها (فروشنده SoC یا ODM) نیز دستهبندی شوند. اگر از ماژول های هسته استفاده می شود، الزامات برای قرار دادن آنها در سیستم فایل به شرح زیر است:
- همه کرنل ها باید پشتیبانی داخلی برای بوت کردن و نصب پارتیشن ها داشته باشند.
- ماژول های هسته باید از یک پارتیشن فقط خواندنی بارگیری شوند.
- برای دستگاه هایی که باید بوت تایید شده داشته باشند، ماژول های هسته باید از پارتیشن های تایید شده بارگیری شوند.
- ماژول های هسته نباید در
/system
قرار بگیرند. - ماژولهای GKI مورد نیاز دستگاه باید از
/system/lib/modules
بارگیری شوند که پیوندی نمادین به/system_dlkm/lib/modules
است. - ماژولهای هسته از فروشنده SoC که برای حالتهای کامل Android یا Charger مورد نیاز هستند، باید در
/vendor/lib/modules
قرار گیرند. - اگر یک پارتیشن ODM وجود داشته باشد، ماژولهای هسته از ODM که برای حالتهای کامل Android یا Charger مورد نیاز هستند باید در
/odm/lib/modules
قرار گیرند. در غیر این صورت، این ماژول ها باید در/vendor/lib/modules
قرار گیرند. - ماژول های هسته از فروشنده SoC و ODM که برای حالت Recovery مورد نیاز هستند باید در
ramfs
بازیابی در/lib/modules
قرار گیرند. - ماژول های هسته مورد نیاز برای هر دو حالت Recovery و Android یا Charger کامل باید هم در
rootfs
بازیابی و هم در پارتیشن های/vendor
یا/odm
(همانطور که در بالا توضیح داده شد) وجود داشته باشند. - ماژولهای هستهای که در حالت بازیابی استفاده میشوند نباید به ماژولهایی که فقط در
/vendor
یا/odm
قرار دارند وابسته باشند، زیرا آن پارتیشنها در حالت Recovery نصب نشدهاند. - ماژولهای هسته فروشنده SoC نباید به ماژولهای هسته ODM وابسته باشند.
در اندروید 7.x و پایینتر، پارتیشنهای /vendor
و /odm
زود نصب نمیشوند . در Android 8.x و بالاتر، برای امکان بارگیری ماژول از این پارتیشنها، مقدماتی برای نصب زودهنگام پارتیشنها برای دستگاههای غیر A/B و A/B در نظر گرفته شده است. این همچنین باعث می شود که پارتیشن ها در هر دو حالت اندروید و شارژر نصب شوند.
پشتیبانی از سیستم ساخت اندروید
در BoardConfig.mk
، ساخت اندروید یک متغیر BOARD_VENDOR_KERNEL_MODULES
را تعریف میکند که فهرست کاملی از ماژولهای هسته در نظر گرفته شده برای تصویر فروشنده را ارائه میدهد. ماژول های فهرست شده در این متغیر در تصویر فروشنده در /lib/modules/
کپی می شوند و پس از نصب در اندروید، در /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
در این مثال، یک مخزن از پیش ساخته شده ماژول هسته فروشنده در محل ذکر شده در بالا به بیلد اندروید نگاشت می شود.
تصویر بازیابی ممکن است حاوی زیرمجموعهای از ماژولهای فروشنده باشد. ساخت اندروید متغیر 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
ساخت اندروید از اجرای depmod
برای تولید فایلهای modules.dep
مورد نیاز در /vendor/lib/modules
و /lib/modules
( recovery ramfs
) مراقبت میکند.
بارگذاری و نسخه سازی ماژول
با فراخوانی modprobe -a
همه ماژولهای هسته را در یک پاس از init.rc*
بارگیری کنید. این امر از هزینه اولیه اولیه سازی مکرر محیط زمان اجرا 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 ...
به طور معمول، یک ماژول هسته باید با هسته ای که ماژول با آن استفاده می شود کامپایل شود (در غیر این صورت هسته از بارگذاری ماژول خودداری می کند). CONFIG_MODVERSIONS
با تشخیص شکستگی در رابط باینری برنامه (ABI) راه حلی را ارائه می دهد. این ویژگی یک مقدار بررسی افزونگی چرخه ای (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
استفاده میکند تغییر میکند (به عنوان مثال، set_cpus_allowed_ptr
در kernel/sched/core.c
). سازگاری با ماژولهای هسته که قبلاً کامپایل شدهاند و از این رابطها استفاده میکنند، شکسته میشود و نیاز است که آن ماژولها با پیکربندی هسته جدید بازسازی شوند.
برای جزئیات بیشتر در مورد CONFIG_MODVERSIONS
، به اسناد موجود در درخت هسته در Documentation/kbuild/modules.rst
مراجعه کنید.