لينكس متعدد النواة موضحًا: من سائقي الأجهزة إلى البيئات الافتراضية

٢٥ سبتمبر ٢٠٢٥

Linux Multi‑Kernel Explained: From Device Drivers to Virtual Environments

عندما يتحدث الناس عن "نواة لينكس"، فإنهم غالبًا ما يقصدون ال نواة لينكس: اللب المفتوح المصدر الضخم الذي يُمكّن كل شيء من هواتف أندرويد إلى الحواسيب الفائقة. لكن في الممارسة العملية، يتعامل المطورون غالبًا مع عدة حالات نواة — سواء من خلال الآلات الافتراضية، أو الترجمة المتقاطعة، أو اختبار السائقين عبر إصدارات مختلفة من النواة. وهنا حيث ستسمع غالبًا مصطلح سير عمل متعدد النوى. خاصةً لمطوري سائقات الأجهزة، القدرة على تشغيل وتبديل والتجربة مع بيئات نواة متعددة ليست مجرد ميزة — بل هي مهارة عملية للبقاء.

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

هذا قراءة طويلة — حوالي 3,300 كلمة — لذا خذ فنجان قهوة، ارتاح، ودعنا نتحدث عن تطوير لينكس متعدد النوى كما يفعل صديقان متحمسان عن الأنظمة من المستوى المنخفض.


ماذا يعني "متعدد النوى"؟

دعونا نوضح المصطلح أولًا. يمكن أن يعني "متعدد النوى" أشياء مختلفة حسب السياق:

  • بحث أنظمة التشغيل الأكاديمي: هناك مشروع بحثي يُسمى بارلفيش يعرّف "متعدد النوى" كهندسة نظام تشغيل مصممة للتوسع عبر المعالجات المتعددة. ليس هذا هو تركيزنا هنا.
  • تطوير لينكس العملي: بالنسبة لمطوري لينكس، يشير "متعدد النوى" عادةً إلى العمل مع عدة بناءات أو حالات لنواة لينكس بالتوازي. غالبًا ما يحتاج المطورون إلى اختبار الوحدات عبر إصدارات مختلفة من النواة، أو استخدام بيئات معزولة متعددة كل منها تعمل نواتها الخاصة.
  • الحاويات الافتراضية: مع الآلات الافتراضية ومشغلات النظام، يمكنك تشغيل عدة نوى لينكس جنبًا إلى جنب، حتى على مضيف ماك أو ويندوز.

إذًا، في هذه المقالة، عندما نقول لينكس متعدد النوى، فإننا نقصد سير العمل العملي للمطورين المتمثل في إدارة عدة حالات نواة لأغراض تطوير السائقين، والاختبار، والتعلم.


لماذا يهم تطوير متعدد النوى؟

إذا كنت قد لعبت من قبل مع سائقات أجهزة لينكس، فأنت تعرف مدى سهولة تدمير نظامك بسطر واحد من الكود معيب. عندما يعمل كودك في مساحة النواة، لا توجد حمايات — فالنواة لا تتسامح مع الأخطاء. يمكن أن يؤدي استرجاع مؤشر خاطئ أو حلقة لا نهائية إلى إيقاف النظام بأكمله.

لهذا السبب تُعد سير عمل متعدد النوى مهمة جدًا:

  • السلامة: لا تخاطر بتدمير نظام المضيف الخاص بك. إذا تعطلت تجربتك النواة، فسيتأثر فقط مثيل الحاوية.
  • إمكانية التكرار: يمكنك اختبار نفس السائق على إصدارات نواة متعددة دون إعادة تثبيت نظامك الأساسي.
  • إمكانية الإعادة: إذا تلف المثيل، فقط احذفه وشغّل مثيلًا جديدًا.
  • العزل: يمكنك الحفاظ على بيئة عملك نظيفة، وفصل هندسة النواة التجريبية عن التطوير اليومي.

هذا مفيد جدًا إذا كنت تتعلم. يمكن للمبتدئين كتابة كود غير آمن دون القلق بشأن كسر جهازهم المحمول.


إعداد المسرح: سائقات الأجهزة والنواة

قبل أن نتعمق أكثر في بيئات متعددة النوى، دعونا نلخص ما هي سائقات الأجهزة وكيف تتفاعل مع النواة.

يُعد savior الجهاز قطعة من البرمجيات تخبر النواة بكيفية التحدث مع قطعة من الأجهزة. النقاط الرئيسية:

  • التطبيقات تعمل في مساحة المستخدم، مع صلاحيات محدودة.
  • السائقات تعمل في مساحة النواة، مع وصول كامل إلى الأجهزة.
  • النواة تعمل كجسر: تُجري التطبيقات المستخدمية مكالمات نظام، تقوم النواة بتوجيهها إلى السائقين، الذين بدورهم يتواصلون مع الأجهزة.

إذًا، عندما تقوم بتوصيل لوحة مفاتيح USB، على سبيل المثال، تعتمد النواة على سائق إدخال USB لترجمة الإشارات الخام إلى أحداث يمكن للتطبيقات المستخدمية فهمها.

في لينكس، يمكن تجميع السائقين بشكل مباشر داخل النواة أو بناؤها كـ وحدات نواة قابلة للتحميل (LKMs). الوحدات مفيدة لأنك يمكنك إدخالها أو حذفها ديناميكيًا دون إعادة تشغيل النظام.


بناء بيئة معزولة متعددة النوى

حسنًا، دعنا نتحدث عن بناء بيئة معزولة لتجربة عدة نوى لينكس. الفكرة بسيطة:

  1. نظام المضيف: هذا هو نظام التشغيل الرئيسي الخاص بك — macOS أو Windows أو حتى لينكس آخر.
  2. نظام الضيف: توزيعة لينكس (عادةً Ubuntu) تعمل داخل الآلة الافتراضية. لديها مثيل نواة خاص بها.

هنا الجزء الرائع: يمكنك تشغيل عدة مثيلات ضيوف، كل منها يشغل نواة خاصة به. هذا هو ملعبك متعدد النوى.

تثبيت Multipass على macOS

إذا كنت تستخدم جهاز Mac، فإن تثبيت Multipass سهل باستخدام Homebrew:

brew install multipass

إذا واجهت مشكلات، جرب:

brew install --cask multipass

بعد التثبيت، اختبره:

multipass --help

يجب أن ترى الأوامر المتاحة.

تشغيل مثيل نواة لينكس جديد

الآن دعنا نطلق آلة افتراضية Ubuntu:

multipass launch --name dev-kernel --mem 2G --disk 10G --cpus 2

هذا ينشئ آلة افتراضية باسم dev-kernel بذاكرة 2 جيجابايت، ومساحة تخزين 10 جيجابايت، و2 وحدات معالجة مركزية.

توصيل بها:

multipass shell dev-kernel

بوم — أنت داخل بيئة لينكس جديدة، تعمل بنواة خاصة بها.

إدارة عدة نوى

تريد مثيلًا آخر بإصدار Ubuntu مختلف؟ سهل:

multipass launch 22.04 --name kernel-22-04
multipass launch 20.04 --name kernel-20-04

كل مثيل يشغل إصدارًا مختلفًا من النواة. يمكنك اختبار سائقيك على كليهما.

عرض جميع النوى الجارية:

multipass list

وإذا كسرت أحدها:

multipass delete dev-kernel
multipass purge

نوى قابلة للتخلص منها بين أصابعك.


كتابة وحدة نواة أولى لك

كفى نظرية — دعنا نكتب وحدة نواة مصغرة لرؤية سير عمل متعدد النوى في العمل.

هنا وحدة نواة بسيطة بلغة C تحسب عدد مرات الوصول إليها.

كود السائق (simple_driver.c)

#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/uaccess.h>

#define DEVICE_NAME "simple_dev"
#define CLASS_NAME  "simple"

static int majorNumber;
static int counter = 0;
static struct class*  simpleClass  = NULL;
static struct device* simpleDevice = NULL;

static ssize_t dev_read(struct file *f, char __user *buf, size_t len, loff_t *off);

static struct file_operations fops = {
   .read = dev_read,
};

static ssize_t dev_read(struct file *f, char __user *buf, size_t len, loff_t *off) {
    char message[64];
    int msg_len;

    counter++;
    msg_len = snprintf(message, sizeof(message), "Driver called %d times\n", counter);

    if (*off >= msg_len) return 0;
    if (copy_to_user(buf, message, msg_len)) return -EFAULT;

    *off += msg_len;
    return msg_len;
}

static int __init simple_init(void) {
    majorNumber = register_chrdev(0, DEVICE_NAME, &fops);
    simpleClass = class_create(THIS_MODULE, CLASS_NAME);
    simpleDevice = device_create(simpleClass, NULL, MKDEV(majorNumber, 0), NULL, DEVICE_NAME);
    printk(KERN_INFO "simple_driver: loaded with major %d\n", majorNumber);
    return 0;
}

static void __exit simple_exit(void) {
    device_destroy(simpleClass, MKDEV(majorNumber, 0));
    class_unregister(simpleClass);
    class_destroy(simpleClass);
    unregister_chrdev(majorNumber, DEVICE_NAME);
    printk(KERN_INFO "simple_driver: unloaded\n");
}

module_init(simple_init);
module_exit(simple_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("InPajama");
MODULE_DESCRIPTION("A simple Linux multi-kernel demo driver");

يُسجّل هذا الوحدة جهازًا حرفياً. في كل مرة تقرأ منها، فإنها تزيد العداد وترجع عدد مرات الوصول إليها.

ملف Make

obj-m += simple_driver.o

all:
	make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules

clean:
	make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

قم بترجمته داخل مثيل نواة النظام:

make

أدخل الوحدة:

sudo insmod simple_driver.ko

تحقق من السجلات:

dmesg | tail

أزلها:

sudo rmmod simple_driver

التفاعل مع مساحة المستخدم

الآن دعنا نكتب تطبيقًا صغيرًا بلغة بايثون للتحدث مع السائق. يعرض السائق نفسه كملف جهاز تحت /dev/simple_dev.

تطبيق بايثون (user_app.py)

with open("/dev/simple_dev", "r") as f:
    data = f.read()
    print("Kernel says:", data.strip())

كلما قمت بتشغيل هذا التطبيق، يزداد العداد في السائق.

python3 user_app.py
python3 user_app.py

الإخراج:

Kernel says: Driver called 1 times
Kernel says: Driver called 2 times

هذا هو الدورة الكلاسيكية: مساحة المستخدم → وحدة النواة → النواة → العودة إلى مساحة المستخدم.


نموذج متعدد النواة في الممارسة

هنا حيث يبرز إعداد متعدد النواة. تخيل أنك قمت بترجمة هذا السائق على نواة Ubuntu 22.04، لكنك تحتاج أيضًا إلى اختباره على 20.04. باستخدام Multipass، يمكنك:

  1. تشغيل كلا المثيلين.
  2. نسخ مصدر السائق إلى كل منهما.
  3. ترجمة مقابل رؤوس كل نواة.
  4. إدخاله واختباره.

هذا هو تطوير متعدد النواة: معاملة كل نواة كصناديق رمل قابلة للتخلص منها لسائقك.

لماذا لا تستخدم ببساطة Docker؟

سؤال جيد. تحتوي حاويات Docker على نواة المضيف المشتركة. إذا كان هدفك اختبار وحدات النواة، فلن يساعدك Docker لأنك لا تستطيع تحميل وحدات نواة مخصصة داخل حاوية دون التأثير على نواة المضيف. أنت بحاجة إلى عزل كامل للنواة، وهو ما يعني استخدام آلات افتراضية.


حماية نظام التشغيل الخاص بمضيفك

إحدى أهم الدروس المستفادة من دورة سائق InPajama هي هذه: لا تقم أبدًا بالتعديل المباشر على نواة نظام التشغيل الخاص بمضيفك. حتى لو كنت تستخدم لينكس كنظام مضيف، أنشئ آلة افتراضية وقم بتجاربك هناك. لماذا؟

  • إذا قمت بتكوين رؤوس النواة بشكل خاطئ، فقد تُعطل نظام البناء الخاص بمضيفك.
  • إذا كانت وحدتك تحتوي على عيب، يمكنك إحداث توقف كامل للنظام.
  • إذا أتلفت ذاكرة النواة، فأنت تخاطر بفقدان البيانات.

باستخدام صناديق الرمل متعددة النواة، يمكنك:

  • العودة الفورية.
  • تشغيل إصدارات متعددة جنبًا إلى جنب.
  • مشاركة الكود من مضيفك عبر دمج SSH وVS Code.

VS Code + SSH: إعداد حلم

كتابة كود النواة في vim داخل آلة افتراضية أمر جيد، لكن سير العمل الحديث يتيح لك الاحتفاظ بمُحررك على المضيف ودفع الكود إلى الآلة الافتراضية. إليك كيف:

  1. ثبت ملحق Remote - SSH في VS Code.
  2. اتصل بـ SSH بمثيل Multipass الخاص بك.
  3. افتح ملفات مصدر السائق مباشرة في VS Code.

الآن لديك IntelliSense، دمج Git، وميزات تحرير حديثة، بينما يحدث الترجمة الفعلية داخل مثيل نواة الصندوق الرملي.


دروس مستفادة من تطوير متعدد النواة

بعد المرور بهذه السير، تبرز بعض النقاط البارزة:

  • العزل هو الحرية: معرفتك أنه يمكنك دائمًا التخلص من مثيل نواة معطوب يجعلك أكثر смелость في التجربة.
  • الرؤوس مهمة: قم دائمًا بتثبيت رؤوس النواة داخل مثيلك (sudo apt install linux-headers-$(uname -r)). بدونها، لا يمكنك ترجمة الوحدات.
  • الانحراف الإصداري حقيقي: التغييرات الصغيرة بين إصدارات النواة يمكن أن تُعطل السائقين. وهذا هو السبب في أن الاختبار عبر نواة متعددة أمر بالغ الأهمية.
  • الأتمتة تُثمر: اكتب سكريبتات لتشغيل المثيلات، وتثبيت الرؤوس، ونسخ المصادر. تصبح سير عمل متعدد النواة فوضوية بدون أتمتة.

الاستنتاج: اعتمد عقلية متعددة النواة

لينكس ليس نواة واحدة فقط — بل هو قاعدة كود حية ومتطورة مع آلاف الإصدارات المنتشرة في البرية. إذا كنت جادًا بشأن تطوير سائقي الأجهزة، فأنت بحاجة إلى اعتماد عقلية متعددة النواة. وهذا يعني:

  • بناء صناديق رمل معزولة باستخدام أدوات مثل Multipass.
  • ممارسة كتابة وتحميل وإلغاء تحميل وحدات النواة.
  • اختبارها عبر نواتين متعددة لضمان التوافق.
  • الحفاظ على نظافة وأمان نظام التشغيل الخاص بمضيفك.

باستخدام هذه المهارات، أنت لا تكتب كودًا فحسب — بل تتعلم لغة النواة. ومرة واحدة تشعر بالراحة في إدارة نواتين متعددة، ستكتشف أن تصحيح الأخطاء والاختبار وحتى المساهمة في لينكس الأساسي يصبحان أقل إرهاقًا بكثير.

إذًا، تقدم: أطلق صندوق الرمل الخاص بك، واكتب سائقك الأول، وشاهد كودك يرقص داخل النواة. عالم متعدد النواة في انتظارك.


الاستنتاج: تطوير متعدد النواة أقل ارتباطًا بالنظريات المجردة وأكثر ارتباطًا بسير العمل العملية. أنشئ أمثلة نواة قابلة للتخلص منها، واختبر سائقيك عبرها، واحافظ على أمان مضيفك. هذه هي الطريقة التي يعمل بها مطورو سائقي لينكس الحديثون.

إذا استمتعت بهذا الاستكشاف العميق، ففكر في الاشتراك للبقاء على اطلاع بمزيد من الاستكشافات الموسعة لأنظمة لينكس وتطوير النواة العملي.