लोड करने योग्य कर्नेल मॉड्यूल

एंड्रॉइड 8.0 में शुरू की गई मॉड्यूल कर्नेल आवश्यकताओं के भाग के रूप में, सभी सिस्टम-ऑन-चिप (SoC) कर्नेल को लोड करने योग्य कर्नेल मॉड्यूल का समर्थन करना चाहिए।

कर्नेल कॉन्फ़िगरेशन विकल्प

लोड करने योग्य कर्नेल मॉड्यूल का समर्थन करने के लिए, सभी सामान्य कर्नेल में android-base.config में निम्नलिखित कर्नेल-कॉन्फिग विकल्प (या उनके कर्नेल-संस्करण समकक्ष) शामिल हैं:

CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
CONFIG_MODVERSIONS=y

सभी डिवाइस कर्नेल को इन विकल्पों को सक्षम करना होगा। कर्नेल मॉड्यूल को जब भी संभव हो अनलोडिंग और रीलोडिंग का भी समर्थन करना चाहिए।

मॉड्यूल पर हस्ताक्षर

जीकेआई विक्रेता मॉड्यूल के लिए मॉड्यूल-हस्ताक्षर समर्थित नहीं है। सत्यापित बूट का समर्थन करने के लिए आवश्यक उपकरणों पर, एंड्रॉइड को उन विभाजनों में कर्नेल मॉड्यूल की आवश्यकता होती है जिनमें dm-verity सक्षम है। इससे उनकी प्रामाणिकता के लिए अलग-अलग मॉड्यूल पर हस्ताक्षर करने की आवश्यकता समाप्त हो जाती है। Android 13 ने GKI मॉड्यूल की अवधारणा पेश की। जीकेआई मॉड्यूल रन टाइम पर जीकेआई और अन्य मॉड्यूल के बीच अंतर करने के लिए कर्नेल के बिल्ड टाइम साइनिंग इंफ्रास्ट्रक्चर का उपयोग करते हैं। अहस्ताक्षरित मॉड्यूल को तब तक लोड करने की अनुमति है जब तक वे केवल अनुमति सूची पर दिखने वाले या अन्य अहस्ताक्षरित मॉड्यूल द्वारा प्रदान किए गए प्रतीकों का उपयोग करते हैं। कर्नेल की बिल्ड टाइम कुंजी जोड़ी का उपयोग करके GKI बिल्ड के दौरान GKI मॉड्यूल पर हस्ताक्षर करने की सुविधा के लिए, GKI कर्नेल कॉन्फ़िगरेशन ने CONFIG_MODULE_SIG_ALL=y सक्षम किया है। डिवाइस कर्नेल निर्माण के दौरान गैर-जीकेआई मॉड्यूल पर हस्ताक्षर करने से बचने के लिए, आपको अपने कर्नेल कॉन्फिग फ़्रैगमेंट के हिस्से के रूप में # CONFIG_MODULE_SIG_ALL is not set जोड़ना होगा।

फ़ाइल स्थान

जबकि एंड्रॉइड 7.x और उससे नीचे के संस्करण कर्नेल मॉड्यूल के खिलाफ अनिवार्य नहीं हैं (और इसमें insmod और rmmod के लिए समर्थन शामिल है), एंड्रॉइड 8.x और उच्चतर पारिस्थितिकी तंत्र में कर्नेल मॉड्यूल के उपयोग की सलाह देते हैं। निम्न तालिका तीन एंड्रॉइड बूट मोड में आवश्यक संभावित बोर्ड-विशिष्ट परिधीय समर्थन दिखाती है।

बूट मोड भंडारण प्रदर्शन कीपैड बैटरी पीएमआईसी टच स्क्रीन एनएफसी, वाई-फाई,
ब्लूटूथ
सेंसर कैमरा
वसूली
अभियोक्ता
एंड्रॉयड

एंड्रॉइड बूट मोड में उपलब्धता के अलावा, कर्नेल मॉड्यूल को उनके मालिक (एसओसी विक्रेता या ओडीएम) के आधार पर भी वर्गीकृत किया जा सकता है। यदि कर्नेल मॉड्यूल का उपयोग किया जा रहा है, तो फ़ाइल सिस्टम में उनके प्लेसमेंट की आवश्यकताएं इस प्रकार हैं:

  • सभी कर्नेल में बूटिंग और माउंटिंग पार्टीशन के लिए अंतर्निहित समर्थन होना चाहिए।
  • कर्नेल मॉड्यूल को केवल पढ़ने योग्य विभाजन से लोड किया जाना चाहिए।
  • सत्यापित बूट के लिए आवश्यक उपकरणों के लिए, कर्नेल मॉड्यूल को सत्यापित विभाजन से लोड किया जाना चाहिए।
  • कर्नेल मॉड्यूल /system में स्थित नहीं होना चाहिए।
  • डिवाइस के लिए आवश्यक GKI मॉड्यूल को /system/lib/modules से लोड किया जाना चाहिए जो /system_dlkm/lib/modules का एक प्रतीकात्मक लिंक है।
  • एसओसी विक्रेता से कर्नेल मॉड्यूल जो पूर्ण एंड्रॉइड या चार्जर मोड के लिए आवश्यक हैं /vendor/lib/modules में स्थित होना चाहिए।
  • यदि कोई ODM विभाजन मौजूद है, तो ODM से कर्नेल मॉड्यूल जो पूर्ण Android या चार्जर मोड के लिए आवश्यक हैं /odm/lib/modules में स्थित होने चाहिए। अन्यथा, ये मॉड्यूल /vendor/lib/modules में स्थित होने चाहिए।
  • एसओसी विक्रेता और ओडीएम से कर्नेल मॉड्यूल जो रिकवरी मोड के लिए आवश्यक हैं, उन्हें /lib/modules पर रिकवरी ramfs में स्थित होना चाहिए।
  • रिकवरी मोड और पूर्ण एंड्रॉइड या चार्जर मोड दोनों के लिए आवश्यक कर्नेल मॉड्यूल रिकवरी rootfs और या तो /vendor या /odm विभाजन (जैसा कि ऊपर वर्णित है) में मौजूद होना चाहिए।
  • पुनर्प्राप्ति मोड में उपयोग किए जाने वाले कर्नेल मॉड्यूल को केवल /vendor या /odm में स्थित मॉड्यूल पर निर्भर नहीं होना चाहिए, क्योंकि वे विभाजन पुनर्प्राप्ति मोड में माउंट नहीं किए गए हैं।
  • SoC विक्रेता कर्नेल मॉड्यूल को ODM कर्नेल मॉड्यूल पर निर्भर नहीं होना चाहिए।

एंड्रॉइड 7.x और उससे पहले के संस्करण में, /vendor और /odm विभाजन जल्दी माउंट नहीं किए गए हैं। एंड्रॉइड 8.x और उच्चतर में, इन विभाजनों से मॉड्यूल लोडिंग को संभव बनाने के लिए, गैर-ए/बी और ए/बी दोनों उपकरणों के लिए विभाजन को जल्दी माउंट करने के प्रावधान किए गए हैं। यह यह भी सुनिश्चित करता है कि विभाजन एंड्रॉइड और चार्जर दोनों मोड में माउंट किए गए हैं।

एंड्रॉइड बिल्ड सिस्टम समर्थन

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

एंड्रॉइड बिल्ड /vendor/lib/modules और /lib/modules ( recovery ramfs ) में आवश्यक modules.dep फ़ाइलों को उत्पन्न करने के लिए depmod चलाने का ख्याल रखता है।

मॉड्यूल लोडिंग और वर्जनिंग

modprobe -a आह्वान करके सभी कर्नेल मॉड्यूल को init.rc* से एक पास में लोड करें। यह modprobe बाइनरी के लिए सी रनटाइम वातावरण को बार-बार प्रारंभ करने के ओवरहेड से बचाता है। modprobe लागू करने के लिए early-init इवेंट को संशोधित किया जा सकता है:

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) में टूट-फूट का पता लगाकर समाधान प्रदान करता है। यह सुविधा कर्नेल में प्रत्येक निर्यातित प्रतीक के प्रोटोटाइप के लिए चक्रीय अतिरेक जांच (सीआरसी) मान की गणना करती है और मानों को कर्नेल के हिस्से के रूप में संग्रहीत करती है; कर्नेल मॉड्यूल द्वारा उपयोग किए जाने वाले प्रतीकों के लिए, मान भी कर्नेल मॉड्यूल में संग्रहीत होते हैं। जब मॉड्यूल लोड किया जाता है, तो मॉड्यूल द्वारा उपयोग किए गए प्रतीकों के मूल्यों की तुलना कर्नेल में मौजूद प्रतीकों से की जाती है। यदि मान मेल खाते हैं, तो मॉड्यूल लोड हो जाता है; अन्यथा लोड विफल हो जाता है।

विक्रेता छवि से अलग कर्नेल छवि के अद्यतन को सक्षम करने के लिए, CONFIG_MODVERSIONS सक्षम करें। ऐसा करने से विक्रेता छवि में मौजूदा कर्नेल मॉड्यूल के साथ संगतता बनाए रखते हुए कर्नेल में छोटे अपडेट (जैसे एलटीएस से बग फिक्स) किए जा सकते हैं। हालाँकि, 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.c में set_cpus_allowed_ptr )। इन इंटरफ़ेस का उपयोग करने वाले पहले से संकलित कर्नेल मॉड्यूल के साथ संगतता टूट जाती है, जिससे उन मॉड्यूल को नए कर्नेल कॉन्फ़िगरेशन के साथ फिर से बनाने की आवश्यकता होती है।

CONFIG_MODVERSIONS पर अधिक विवरण के लिए, कर्नेल ट्री में Documentation/kbuild/modules.rst पर दस्तावेज़ देखें।