ماژول نویسی برای هسته لینوکس (قسمت اول)(1206 مجموع کلمات موجود در متن) (10776 بار مطالعه شده است) 
ماژول نویسی
برای هسته لینوکس (قسمت
اول)
ماژول هسته
چیست؟
اولیــن سوالی
کــه ممکن است به ذهن خواننده برسد این
است که ماژول هسته دقیقا چیست؟ در پاسخ
باید گفت که ماژولها
تـکه کدهایی هـستند که در حین اجرای هسته
لینوکس می توانند وارد آن شده و یا از آن
خارج شوند.
این
تکه کدها عملکرد هسته را بدون نیاز به راه
اندازی دوباره کامپیوتر توسعه میدهند.
به عنوان مثال
یــک نــوع از مــاژولها
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
از
هسته خارج شده است.در
قسمت های بعدی با مثال های بیشتر به دیگر
جزئیات ماژول نویسی برای هسته لینوکس
خواهیم پرداخت.

PDF Version
ترجمه
و تکمیل :
سعید
تقویs.taghavi@ece.ut.ac.ir
منابع
:
1)
http://www.tldp.org/LDP/lkmpg/2.6/html
2)
http://www.linuxhq.com/guides/LKMPG/mpg.html |