लोड किए जा सकने वाले कर्नेल मॉड्यूल

Android 8.0 में मॉड्यूल के लिए, kernel की ज़रूरी शर्तों के तहत, सभी सिस्टम-ऑन-चिप (SoC) के kernel, लोड किए जा सकने वाले kernel मॉड्यूल के साथ काम करने चाहिए.

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

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

CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
CONFIG_MODVERSIONS=y

सभी डिवाइस के कर्नेल में ये विकल्प चालू होने चाहिए. कर्नेल मॉड्यूल को भी, जब भी हो सके, अनलोड और फिर से लोड करने की सुविधा देनी चाहिए.

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

GKI वेंडर मॉड्यूल के लिए, मॉड्यूल-साइनिंग की सुविधा काम नहीं करती. जिन डिवाइसों पर वेरिफ़ाइड बूट की सुविधा काम करनी चाहिए उन पर, Android के लिए यह ज़रूरी है कि कर्नेल मॉड्यूल उन पार्टीशन में हों जिनमें 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 और इससे पहले के वर्शन में, कर्नेल मॉड्यूल का इस्तेमाल करना ज़रूरी नहीं है. साथ ही, इनमें insmod और rmmod के लिए सहायता भी शामिल है. हालांकि, Android 8.x और इसके बाद के वर्शन में, नेटवर्क में कर्नेल मॉड्यूल का इस्तेमाल करने का सुझाव दिया जाता है. यहां दी गई टेबल में, बोर्ड के हिसाब से, Android के तीन बूट मोड में काम करने वाले संभावित पेरिफ़रल के बारे में बताया गया है.

बूट मोड स्टोरेज डिसप्ले कीपैड बैटरी पीएमआईसी टचस्क्रीन एनएफ़सी, वाई-फ़ाई,
ब्लूटूथ
सेंसर कैमरा
रिकवरी
चार्जर
Android

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

  • सभी कर्नेल में, बूट करने और पार्टिशन को माउंट करने के लिए, पहले से मौजूद सुविधा होनी चाहिए.
  • कर्नेल मॉड्यूल, रीड-ओनली पार्टीशन से लोड होने चाहिए.
  • जिन डिवाइसों के लिए वेरिफ़ाइड बूट मोड की ज़रूरत होती है उनके लिए, कोर मॉड्यूल को पुष्टि किए गए सेगमेंट से लोड किया जाना चाहिए.
  • कर्नेल मॉड्यूल, /system में नहीं होने चाहिए.
  • डिवाइस के लिए ज़रूरी GKI मॉड्यूल, /system/lib/modules से लोड किए जाने चाहिए. यह /system_dlkm/lib/modules का सिंबल लिंक है.
  • SoC वेंडर के ऐसे कर्नेल मॉड्यूल जो Android के सभी वर्शन या चार्जर मोड के लिए ज़रूरी हैं उन्हें /vendor/lib/modules में होना चाहिए.
  • अगर कोई ओडीएम पार्टीशन मौजूद है, तो ओडीएम के ऐसे कर्नेल मॉड्यूल जो फ़ुल Android या चार्जर मोड के लिए ज़रूरी हैं, वे /odm/lib/modules में होने चाहिए. अगर ऐसा नहीं है, तो ये मॉड्यूल /vendor/lib/modules में होने चाहिए.
  • SoC वेंडर और ODM के वे कर्नेल मॉड्यूल जो रिकवरी मोड के लिए ज़रूरी हैं उन्हें /lib/modules पर रिकवरी ramfs में होना चाहिए.
  • रिकवरी मोड और फ़ुल Android या चार्जर मोड, दोनों के लिए ज़रूरी कर्नेल मॉड्यूल, रिकवरी rootfs और /vendor या /odm वाले दोनों सेक्शन में मौजूद होने चाहिए (जैसा कि ऊपर बताया गया है).
  • रिकवरी मोड में इस्तेमाल किए जाने वाले कर्नेल मॉड्यूल, सिर्फ़ /vendor या /odm में मौजूद मॉड्यूल पर निर्भर नहीं होने चाहिए. ऐसा इसलिए, क्योंकि ये पार्टीशन रिकवरी मोड में माउंट नहीं होते.
  • 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 बिल्ड, /vendor/lib/modules और /lib/modules (recovery ramfs) में ज़रूरी modules.dep फ़ाइलें जनरेट करने के लिए, depmod को चलाता है.

मॉड्यूल लोड करना और वर्शन बनाना

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

वेंडर इमेज से अलग, कर्नेल इमेज को अपडेट करने की सुविधा चालू करने के लिए, CONFIG_MODVERSIONS को चालू करें. ऐसा करने से, वेंडर इमेज में मौजूद मौजूदा कर्नेल मॉड्यूल के साथ काम करते हुए, कर्नेल में छोटे अपडेट (जैसे, एलटीएस से बग ठीक करना) किए जा सकते हैं. हालांकि, CONFIG_MODVERSIONS, एबीआई के गड़बड़ी को अपने-आप ठीक नहीं करता. अगर सोर्स में बदलाव करने या कर्नेल कॉन्फ़िगरेशन में बदलाव करने की वजह से, कर्नेल में किसी एक्सपोर्ट किए गए सिंबल का प्रोटोटाइप बदल जाता है, तो उस सिंबल का इस्तेमाल करने वाले कर्नेल मॉड्यूल के साथ काम नहीं करता. ऐसे मामलों में, कर्नेल मॉड्यूल को फिर से कंपाइल करना होगा.

उदाहरण के लिए, task_struct स्ट्रक्चर में (include/linux/sched.h में तय किया गया) कई फ़ील्ड होते हैं, जो कि kernel कॉन्फ़िगरेशन के आधार पर, शर्त के मुताबिक शामिल किए जाते हैं. 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 पर मौजूद कर्नेल ट्री में दस्तावेज़ देखें.