init_module(2)

الاسم
init_module, finit_module - تحميل وحدة نواة

المكتبة
مكتبة سي المعيارية (libc، -lc)

موجز
#include <linux/module.h>    /* Definition of MODULE_* constants */
#include <sys/syscall.h>     /* Definition of SYS_* constants */
#include <unistd.h>

int syscall(unsigned long size;
SYS_init_module,
            void module_image[size], unsigned long size,
            const char *param_values);
int syscall(SYS_finit_module, int fd,
            const char *param_values, int flags);

ملاحظة: لا توفر glibc أغلفة لنداءات النظام هذه، مما يستلزم استخدام syscall(2).

الوصف
init_module() يحمل صورة ELF إلى مساحة النواة، ويؤدي أي إعادة توطين رموز ضرورية، ويُهيئ معاملات الوحدة إلى القيم المقدمة من المستدعي، ثم يشغل دالة init للوحدة. تتطلب استدعاء النظام هذا صلاحية.

تشير وسيطة module_image إلى مخزن مؤقت يحتوي على الصورة الثنائية المراد تحميلها؛ تحدد size حجم ذلك المخزن. يجب أن تكون صورة الوحدة صورة ELF صالحة، مبنية للنواة الجارية.

وسيطة param_values هي سلسلة تحتوي على مواصفات مفصولة بمسافات لقيم معاملات الوحدة (المعرفة داخل الوحدة باستخدام module_param() و module_param_array()). تحلل النواة هذه السلسلة وتهيئ المعاملات المحددة. كل مواصفات معامل لها الشكل:

name[ =value [,value...]]

اسم المعامل name هو أحد تلك المعرفة داخل الوحدة باستخدام module_param() (انظر ملف مصدر نواة لينكس include/linux/moduleparam.h). قيمة المعامل value اختيارية في حالة معاملات bool و invbool. تُحدد قيم معاملات المصفوفة كقائمة مفصولة بفواصل.

  finit_module()
استدعاء النظام finit_module() يشبه init_module()، لكنه يقرأ الوحدة المراد تحميلها من واصف الملف fd. يكون مفيدًا عندما يمكن تحديد أصالة وحدة نواة من موقعها في نظام الملفات؛ في الحالات التي يكون فيها ذلك ممكنًا، يمكن تجنب عبء استخدام الوحدات الموقعة تشفيريًا لتحديد أصالة الوحدة. وسيطة param_values كما في init_module().

تعدل وسيطة flags عملية finit_module(). هي قيمة قناع بتات تُنشأ بجمع OR معًا صفرًا أو أكثر من الأعلام التالية:

MODULE_INIT_IGNORE_MODVERSIONS
    تجاهل تجزئات إصدار الرموز.

MODULE_INIT_IGNORE_VERMAGIC
    تجاهل سحر إصدار النواة.

MODULE_INIT_COMPRESSED_FILE (منذ لينكس 5.17)
    استخدام فك ضغط الوحدة داخل النواة.

هناك بعض فحوصات الأمان المضمنة في الوحدة لضمان مطابقتها للنواة التي تُحمل ضدها. تُسجل هذه الفحوصات عند بناء الوحدة وتُتحقق عند تحميل الوحدة. أولاً، تسجل الوحدة سلسلة "vermagic" تحتوي على رقم إصدار النواة والميزات البارزة (مثل نوع وحدة المعالجة المركزية). ثانيًا، إذا بُنيت الوحدة مع تمكين خيار التهيئة CONFIG_MODVERSIONS، يُسجل تجزئة إصدار لكل رمز تستخدمه الوحدة. تعتمد هذه التجزئة على أنواع الوسائط وقيمة الإرجاع للدالة المسماة بالرمز. في هذه الحالة، يُتجاهل رقم إصدار النواة داخل سلسلة "vermagic"، حيث يُفترض أن تجزئات إصدار الرموز موثوقة بما يكفي.

استخدام العلم MODULE_INIT_IGNORE_VERMAGIC يشير إلى أن سلسلة "vermagic" يجب تجاهلها، والعلم MODULE_INIT_IGNORE_MODVERSIONS يشير إلى أن تجزئات إصدار الرموز يجب تجاهلها. إذا بُنيت النواة للسماح بالتحميل القسري (أي، مهيأة مع CONFIG_MODULE_FORCE_LOAD)، يستمر التحميل، وإلا يفشل مع الخطأ ENOEXEC كما هو متوقع للوحدات المشوهة.

إذا بُنيت النواة مع CONFIG_MODULE_DECOMPRESS، يمكن استخدام ميزة فك الضغط داخل النواة. يمكن لرمز مساحة المستخدم التحقق مما إذا كانت النواة تدعم فك الضغط بقراءة السمة /sys/module/compression. إذا دعمت النواة فك الضغط، يمكن تمرير الملف المضغوط مباشرة إلى finit_module() باستخدام العلم MODULE_INIT_COMPRESSED_FILE. يدعم مفكك ضغط الوحدة داخل النواة خوارزميات الضغط التالية:

    •   gzip (منذ لينكس 5.17)
    •   xz (منذ لينكس 5.17)
    •   zstd (منذ لينكس 6.2)

تنفذ النواة طريقة فك ضغط واحدة فقط. تُختار هذه الطريقة أثناء توليد الوحدة وفقًا لطريقة الضغط المختارة في تهيئة النواة.

قيمة الإرجاع
عند النجاح، تُرجع استدعاءات النظام هذه 0. عند الخطأ، يُرجع -1 ويُضبط errno للإشارة إلى الخطأ.

الأخطاء

EBADMSG (منذ لينكس 3.7)
    توقيع الوحدة ذو تنسيق خاطئ.

EBUSY
    انتهاء المهلة أثناء محاولة حل مرجع رمز بواسطة هذه الوحدة.

EFAULT
    وسيطة عنوان تشير إلى موقع خارج مساحة العنوان القابلة للوصول للعملية.

ENOKEY (منذ لينكس 3.7)
    توقيع الوحدة غير صالح أو لا يملك النواة مفتاحًا لهذه الوحدة. يُرجع هذا الخطأ فقط إذا ضُبطت النواة مع CONFIG_MODULE_SIG_FORCE؛ إذا لم تضبط النواة مع هذا الخيار، فإن الوحدة غير الصالحة أو غير الموقعة تشوه النواة ببساطة.

ENOMEM
    نفدت الذاكرة.

EPERM
    لم يكن المتصل مميزًا (لم يملك صلاحية CAP_SYS_MODULE)، أو تحميل الوحدة معطل (انظر /proc/sys/kernel/modules_disabled في proc(5)).

قد تحدث الأخطاء التالية بالإضافة إلى ذلك لـ init_module():

EEXIST
    وحدة بهذا الاسم محملة بالفعل.

EINVAL
    param_values غير صالح، أو جزء ما من صورة ELF في module_image يحتوي على تناقضات.

ENOEXEC
    الصورة الثنائية المقدمة في module_image ليست صورة ELF، أو هي صورة ELF غير صالحة أو لبنية مختلفة.

قد تحدث الأخطاء التالية بالإضافة إلى ذلك لـ finit_module():

EBADF
    الملف المشار إليه بـ fd لم يُفتح للقراءة.

EFBIG
    الملف المشار إليه بـ fd كبير جدًا.

EINVAL
    flags غير صالحة.

EINVAL
    فشلت فحوصات السلامة لمفكك الضغط، أثناء تحميل وحدة مضغوطة مع تعيين العلم MODULE_INIT_COMPRESSED_FILE.

ENOEXEC
    fd لا يشير إلى ملف مفتوح.

EOPNOTSUPP (منذ لينكس 5.17)
    العلم MODULE_INIT_COMPRESSED_FILE مضبوط لتحميل وحدة مضغوطة، وبُنيت النواة بدون CONFIG_MODULE_DECOMPRESS.

ETXTBSY (منذ لينكس 4.7)
    الملف المشار إليه بـ fd مفتوح للقراءة والكتابة.

بالإضافة إلى الأخطاء أعلاه، إذا نُفذت دالة init للوحدة وأرجعت خطأ، فإن init_module() أو finit_module() تفشل ويُضبط errno على القيمة التي أرجعتها دالة init.

المعايير
لينكس.

التاريخ

finit_module()
    لينكس 3.8.

استدعاء النظام init_module() غير مدعوم من glibc. لا يُقدم أي تصريح في رؤوس glibc، ولكن، من خلال غرابة تاريخية، أصدرت إصدارات glibc قبل glibc 2.23 واجهة ABI لاستدعاء النظام هذا. لذلك، لاستخدام استدعاء النظام هذا، يكفي (قبل glibc 2.23) التصريح يدويًا بالواجهة في شفرتك؛ بدلاً من ذلك، يمكنك استدعاء استدعاء النظام باستخدام syscall(2).

  لينكس 2.4 وما قبله
في لينكس 2.4 والإصدارات الأقدم، كان استدعاء النظام init_module() مختلفًا تمامًا:

#include <linux/module.h>

int init_module(const char *name, struct module *image);

(يمكن لتطبيقات مساحة المستخدم اكتشاف أي إصدار من init_module() متاح باستدعاء query_module()؛ يفشل الاستدعاء الأخير مع الخطأ ENOSYS على لينكس 2.6 والإصدارات الأحدث.)

الإصدار الأقدم من استدعاء النظام يحمل صورة الوحدة المعاد توطينها المشار إليها بـ image إلى مساحة النواة ويشغل دالة init للوحدة. المتصل مسؤول عن توفير الصورة المعاد توطينها (منذ لينكس 2.6، يقوم استدعاء النظام init_module() بإعادة التوطين).

تبدأ صورة الوحدة ببنية وحدة ويتبعها كود وبيانات حسب الاقتضاء. منذ لينكس 2.2، تُعرف بنية الوحدة كما يلي:

    struct module {
        unsigned long         size_of_struct;
        struct module        *next;
        const char           *name;
        unsigned long         size;
        long                  usecount;
        unsigned long         flags;
        unsigned int          nsyms;
        unsigned int          ndeps;
        struct module_symbol *syms;
        struct module_ref    *deps;
        struct module_ref    *refs;
        typeof(int (void))   *init;
        typeof(void (void))  *cleanup;
        const struct exception_table_entry *ex_table_start;
        const struct exception_table_entry *ex_table_end;
    #ifdef __alpha__
        unsigned long gp;
    #endif
    };

جميع حقول المؤشر، باستثناء next و refs، يُتوقع أن تشير داخل جسم الوحدة وتُهيأ كما هو مناسب لمساحة النواة، أي معاد توطينها مع بقية الوحدة.

ملاحظات
يمكن العثور على معلومات حول الوحدات المحملة حاليًا في /proc/modules وفي أشجار الملفات تحت الدلائل الفرعية لكل وحدة تحت /sys/module.

انظر ملف مصدر نواة لينكس include/linux/module.h للحصول على بعض المعلومات الخلفية المفيدة.

انظر أيضًا
create_module(2)، delete_module(2)، query_module(2)، lsmod(8)، modprobe(8)

ترجمة
تُرجمت هذه الصفحة من الدليل بواسطة زايد السعيدي <zayed.alsaidi@gmail.com>

هذه الترجمة هي وثيقة مجانية؛ راجع رخصة جنو العامة الإصدار 3 (https://www.gnu.org/licenses/gpl-3.0.html) أو ما بعده للاطلاع على شروط حقوق النشر. لا توجد أي ضمانات.

إذا وجدت أي أخطاء في ترجمة صفحة الدليل هذه، يرجى إرسال بريد إلكتروني إلى قائمة بريد المترجمين: kde-l10n-ar@kde.org.