این مقاله قشنگ که ادامه تقدیمتان می گردد در جدید ترین شماره( شماره یازدهم) نشریه الکترونیک لینوکس منتشر شده است بدلیل کارایی فوق العاده ماژول ها و مخصوصا استفاده آنها در کارهای شبکه ای توصیه می کنم حتما مطالعه بفرمایید...

ماژول هسته چیست؟

اولیــن سوالی کــه ممکن است به ذهن خواننده برسد این است که ماژول هسته دقیقا چیست؟ در پاسخ باید گفت که ماژول‌ها تـکه کدهایی هـستند که در حین اجرای هسته لینوکس می توانند وارد آن شده و یا از آن خارج شوند. این تکه کدها عملکرد هسته را بدون نیاز به راه اندازی دوباره کامپیوتر توسعه می‌دهند.

به عنوان مثال یــک نــوع از مــاژول‌ها device driver ها هستند کـه به هسته امکان استفاده از قابلیت سخت افزار ها را می‌دهند.

اگر ماژول‌ها وجود نداشتند، بـرای هر قابلیتی که می‌خواستیم بــه هسته اضافه کنیم یـا از آن کم کنیم، می‌بایستی یک بار هسته را کامپایل می‌کردیم و برای استفاده از ان قابلیت یا حذف آن یک بار سیستم را از نو راه اندازی می‌کردیم.


ماژول ها چگونه به هسته وارد می شوند؟

شما می‌توانید بــا اجرای دستور lsmod ماژول‌هایی کــه هــم اکنـون در هسته وارد شده‌انـد را ببیـنـید و از اطـلاعات آنها باخبر شوید. این دستور اطلاعات خود را از فایل proc/modules/ دریافت می‌کند.

هنگامی که هسته، به امکان و عملکردی نیاز دارد که هم اکنون در آن نیست، یکــی از deamon های آن بــه نـام kmod دستور modprobe را اجرا می‌کند تا ماژول مربوطه که آن عملکرد را دارد وارد هسته شود . هنـگامی که modprobe اجرا می شود به آن یک رشته کاراکتر به دو صورت زیر داده می‌شود:

۱) نام ماژول مانند softdog یا ppp

۲) یک مشخصه کلی مانند char-major-10-30

اگر حالت اول بــه modprobe داده شود، ایــن دستور بـه دنبال فایلی به نام softdog.ko یا ppp.ko با روشی که در ادامه می‌آید می‌گردد. ولی اگــر حــالـت دوم بــه modprobe داده شود، ایــن دستــور ابـــتدا بــه دنــبال رشتـه کاراکتر در فایل etc/modprobe.conf/ می گردد و اگر توانست alias یا مستعاری مانند:

alias char-major-10-30 softdog

پیدا کند، متوجه می‌شود کــه ایــن نــام کلی که در اینجا char-major-10-30 است به ماژول softdog اشاره می‌کــند که فایل ماژول آن softdof.ko می‌باشد.

در مرحله بعد modprobe فایل lib/modules/version/modules.dep/ را باز کرده و به دنبال ماژول‌هایی می‌گــردد کـه باید قبل از ماژول مورد نظر به هسته وارد شوند. ایــن فــایل به وسیله دستور depmod -a ایجاد می‌شود و حــاوی وابستگی بین ماژول هاست.

به عنوان مثال اگر به دنبال مــاژول msdos.ko در ایــن فــایل بگردید خواهید دید که به ماژول دیگری به نام fat.ko وابسته است یعنی برای اینکه msdos.ko وارد هسته شود حتما باید قبل از ان fat.ko وارد شده باشد. ایــن مسـاله برای fat.ko نیز تــکــرار شده تــا بـه مرحله‌ای برسیم که دیگر وابستگی موجود نباشد. در نهایت modprobe دستور insmod را به کار می‌برد تا ابتدا وابستگی‌ها را به هسته وارد کرده و در نهایت ماژول مورد نظر ما به هسته وارد می‌شود.

پس modprobe وظــیـفه پـیـدا کــردن مــاژول، تعیین وابستگیهای آن و وارد کردن آن بــه هستــه بــه وسیــله صـدا کردن insmod را دارد در حالی که insmod فقط وظیفه وارد کردن آن ماژول به هسته را دارد.

به عنوان مثال اگر بخواهیم به صورت دستی msdos.ko را وارد هسته کنیم به صورت زیر عمل می کنیم :

insmod /lib/modules/2.6.11/kernel/fs/fat/fat.ko

insmod /lib/modules/2.6.11/kernel/fs/fat/msdos.ko
معادل دو دستور بالا با modprobe به صورت زیر است:

modprobe msdos
مطلب قابل ذکر این است که insmod مسیر کامل تا فایل ماژول را می‌خواهد در حالی که modprobe فقط نـــام ماژول را می‌گیرد.


قبل از شروع

قبل از اینکه وارد کد و کدزنی شویم چند نکته مهم را بررسی می‌کنیم:

۱) modversioning: یــک ماژول کـه برای یک هسته خاص کامپایل شده است بر روی هسته دیگر load نخواهد شد مگر اینکه شــما CONFIG_MODVERSIONS را در هسته فــعــال کنــیـد. در قـســمت‌های بـعــد بیشتر به این مقوله خواهیم پرداخت.

۲) ماژول‌ها نمی‌توانند چــیزی به غیر از خطاها و هشدارها را بر روی صفحه نمایش نـشان دهند. آنها بــرای نـشان دادن اطلاعات خود، آنها را در log فایلها می‌نویسند.

۳) مورد سوم که کاملا مورد قبول بنده نمی‌باشد این است که نویسنده می گوید:

«اغلب توزیع کنندگان لینوکس کد منبع هسته را که مورد Patch نیز قرار گرفته به طرز غیر استانداردی توزیع می‌کنند که ممکن است باعث ایجاد مشکلاتی شود. یکی از شایع ترین این مشکلات فایل های ناقص Header برای هسته لینوکس هستند. شما برای ماژول نویسی نیاز دارید که فایل های Header زیــادی را در کـــدهای خـود ضمیمه کـنـید و فایــلهای ناقص اغلب فایل هایی هستند که برای ماژول نویسی به کار می روند.» نویــسنده پیشنهاد می‌کند کـه برای جلوگیری از این مشکل هسته را برای خود کامپایل کنید.


یک مثال – ساده ترین ماژول

برای شروع از مثال سنتی Hello World! شروع می‌کنیم. فایلی به نام hello-1.c باز کرده و کد C زیر را در آن بنویسید:

include <linux/module.h> /*needed by all modules */
#include <linux/kernel.h> /*needed for Macros like KERN_INFO */

int init_module(void) /* this
function is called as initialization for all modules */

{
printk(KERN_INFO “Hello World1.\n”);

/* if this function returns non
zero means init_module failed and
this module can’t be loaded .
*/
return 0;
}

void cleanup_module(void) /* it is
called when module is terminated and unloaded */
{
printk( KERN_INFO “Goodbye World1.\n”);
}
هــر ماژول هسته‌ای حداقل بایستی ۲ تابع داشته باشد. اولـی تابع شروع که init_module() نامیده می‌شــود و هنگام load شدن ماژول در هسته صدا زده می‌شود و دیــگــری تــابــع پــایان که cleanup_module() نامیده می‌شــود و هنگام unload شدن ماژول از هسته صدا زده می‌شود. در قسمت‌های بـعد به این موضوع می‌پـردازیم که بعد از هسته 2.3.13 شما می‌توانید هــر نـــام دیــگری بــرای این دو تــابع قرار دهید. بــا ایـــن حــال خـیـلی از افـــراد هنـــوز از ایـن استاندارد قدیمی استفاده می‌کنند. دو فــایــل Header در ایــن کــد ضمیمه شده‌اند. یــکی linux/module.h می‌باشد که برای هر مــاژولی مــورد نیاز است و تعریف خیلی از توابع را در خـود دارد و دیــگــری linux/kernel.h می‌باشد کــه حــاوی تعدادی ماکرو می‌باشد مانند KERN_INFO.


مختصری درباره printk()

بر خلاف آن چیزی که ممکن است درباره printk() تصور کنید این تابع چیزی در صفحه نمایش چاپ نمی کند و برای کار با کاربر نیست. ایــن تــابع برای مکانیزم log هستــه بـه کار میــرود . هــر printk() بــا یـک اولویت می‌آید کــه در ایـن مثال مــاکــروی KERN_INFO بــرای ایــن منظور بــه کــار رفته است. تـعـداد ۸ اولــویت وجــود دارند کــه بــه صــورت مـاکرو در فــایــل linux/kernel.h تعـــریف شــده‌انــد. اگـــر شـمــا ایـــن اولــویــت را تـعــیــین نـکــنــیــد بـــه طـــور پــیــش فـــرض DEFAULT_MESSAGE_LOGLEVEL به آن تخصیص می‌یابد .

اگــر این اولویت کمــتر از اولــویت int console_loglevel (که در linux/kernel.h تعریف شده) باشــد، message در دستور printk() بر روی صفحه ظاهر می‌شود. اگــر syslogd و یــا klogd در سیستم در حــال اجرا باشند این message در فایل var/log/messages/ نوشته می‌شود.


کامپایل ماژول های هسته

ماژول های هسته کمی متفاوت نسبت به برنامه های معمولی کامپایل می‌شوند. بــرای ایـنکه بتوانید یک ماژول هسته را بــه درستــی کامپایل کنید، نیاز به تنظیمات بسیار زیادی دارید. بــا پیـچیده‌تر شــدن ماژول‌ها ایـن تنظیمات پیچیده‌تر می‌شوند. خــوشبختانه مکانیزمی به نام kbuild وجود دارد که تمام این تنظیمات را انجام می‌دهد. بـرای اگاهی بیشتر از ایـن مکانیزم به فایلهای مستند هسته که در آدرس linux/Documentation/kbuild/modules.txt کد منبع هسته مـوجـود است مراجعه کنید. بــرای اینکه بتوانیم از مکـانیزم kbuild استفاده کنیم، بایستی Makefile ای با استاندارد آن بنویسیم. برای این کار یک فایل به نام Makefile باز کرده و دستورات زیر را در آن بنویسید:

obj-m += hello-1.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 ماژول خود را کامپایل کنید. در هسته 2.6 بــه بــعد از پسوند ko بــرای نــامیدن مـــاژول‌های هسته استفاده شده است که به راحتی قابل تمییز از o که پسوند فایل های object است می‌باشد.

برای بدست آوردن اطلاعاتی از ماژول خود دستور زیر را اجرا کنید:

modinfo hello-1.ko
برای وارد کردن ماژول خود در هسته از دستور زیر استفاده کنید:

insmod ./hello-1.ko
اگر بعد از اجرای این دستور فایل var/log/messages/ را باز کرده و به انتهای آن بروید، خواهید دیــد کـه ماژول hello-1 در هسته load شده است. با دستور lsmod نیز ماژول load شده را خواهید دید. بــرای unload یــا خارج کردن ماژول خود از هسته از دستور rmmod به صورت زیر استفاده کنید :

rmmod hello-1
دوباره اگر فایل var/log/messages/ را بــاز کنید و به انتهای آن بــروید خواهید دید که ماژول hello-1 از هسته خارج شده است.در قسمت های بعدی با مثال های بیشتر به دیگر جزئیات ماژول نویسی برای هسته لینوکس خواهیم پرداخت.

ترجمه :آقای سعید تقوی s.taghavi@ece.ut.ac.ir

منابع :
[lLEFT]
1) http://www.tldp.org/LDP/lkmpg/2.6/html
2) http://www.linuxhq.com/guides/LKMPG/mpg.html[/LEFT]



موضوعات مشابه: