ماژول نویسی برای هسته لینوکس (قسمت ششم)(645 مجموع کلمات موجود در متن) (5991 بار مطالعه شده است)
ماژول نویسی
برای هسته لینوکس (قسمت
ششم)
ثبت
(register)
یک
دستگاه در هسته
همان
طور که در قسمت قبل بحث کردیم، دستگاههای
کاراکتری از طریق فـــایلهای دستگاه
کــه معمولا در dev/
قرار
میگیــرند قــابل دسترسی هستند.
در
قسمت قبــل به این موضوع نیز پرداختیم که
عدد اصلی هــر فایل دستگاه نشان میدهد
که دستگاه توسط چه راه اندازی کنترل شده
و عــدد فـــرعی تــوسط خود راه انداز
بــرای تمایز بین دستگاههای تحت کنترل
خود به کار میرود.
اضافه
کردن یک راه انداز به سیستم به معنی ثبت
آن در هسته است.
مترادف
این جمله آن است کــه در هنــگام شروع به
کار ماژول (initialization)،
به آن یــک عــدد اصلی نسبت داده شــود.
شما
میتوانید این کــار را بـــا استـــفاده
از تابع register_chrdev
که
در <linux/fs.h>
تعریف
شده است انجام دهید:
int
register_chrdev(unsigned int major, const char *name,
struct file_operations
fops);
unsigned int major
عـــدد
اصلی مورد درخواست و const
char *name نام
دستگاه شما اســت کــه در proc/devices/
ظاهر
خواهد شد و struct
file_operations *fops نیز
اشارهگــر بــه سـاختار داده
file_operations
مورد
استفاده راه انداز هستند.
اگر
مقدار بازگشتی این تابع منفی باشد ثبت
دستگاه در هسته موفقیت آمیز نبوده است.
به این
نکته توجه داشته باشید که ما عدد فرعیای
بـــه ایــن تابع پاس نکردیم چون که این
موضوع برای هسته اهمیتی ندارد و ماژول
خود از ان استفاده میکند.
سوال
بسیار مهمیکــه ممکن است مطــرح شــود
این است که چگونه عدد اصلی ای به تابع
register_chrdev
بدهیم
و مطمئن باشیم که قبلا توسط راه انداز
دیگری اختیار نشده است؟
آسانترین
راه برای ایــن کار رجــوع بــه فایل
linux/Documentation/devices.txt
از
کد منبع هسته لینوکس و انتخاب یک عدد رزرو
نشده است.
مطمئنا
این راه بدترین راه است چــون هیـــچ
اطمینانی در قابـــل استفاده بودن آن
عــدد اصــلـی نمیدهد.
بهترین
راه آنست کــه شما از خود هسته بخواهید
که به صورت دینامیک یک عدد اصلی در اختیار
شما بگذارد.
اگر
ورودی اول تابع register_chrdev
که
همان unsigned
int major است
را صفر قرار دهید، هستـه یک عدد اصلی را
به عنوان مقدار بازگشتی تابع register_chrdev
به
شما باز میگرداند.
خروج
(unregister)
یک
دستگاه از هسته
ما
نمیتوانیم اجازه دهیم که هر هنگام یک
ماژول هسته rmmod
شــود.
اگــر
فایل دستگاه توسط یک پروسه بــاز شـده
باشد و مــا مــاژول را از هسته خارج کنیم،
آن پروسه بـه آن قسمت از حافظه که آدرس آن
تــابــع از راه انـــداز است، دسترسی
داشته و میتواند آن تابع را صدا نماید.
اگر
خیلی خوش شانس باشیم و کــد جدیدی در آن
آدرس load
نشده
باشد، فقط یک پیغام خطا دریافت خواهیم
کرد.
ولــی
اگـر خیلی خوش شانس نباشیم و ماژول جدیدی
در آن ادرس load
شده
باشد، به این معنی است که در میــان تابع
جدیدی از هستــه خــواهیم پرید.
نتیجه
این کار به هیچ وجه قابل پیش بینی نیست
ولی در اکثر موارد اتفاقهای نسبتا
ناگواری در سیستم به بار میآید.
معمولا
برای اینکه شما اجازه انجام کاری را ندهید،
یک پیغام خطا (یک
عدد منفی)
توسط
آن تابع انجام دهنده کــار بر خواهید
گردانــد.
در
مــورد تابع cleanup_module
ایــن
کار ممکن نیست، چـون ایــن تــابــع void
بـر
میگرداند (چیزی
بر نمیگرداند).
راه
متداول این کار وجود یک شمارنده در ماژول
است کـه تعداد پروسسهایی که از ماژول
استفاده میکنند را نگه میدارد.
شما
میتوانید مقدار این شمارنده را در سومین
فیلد proc/modules/
مشاهده
کنیــد.
اگـر
این مقدار غیر صفر باشد دستور rmmod
با
شکست مواجه خواهد شد.
توجه
داشته باشیــد کــه شما نبایستی این
شمـارنده را در cleanup_module
چک
نمایید بدلیل اینکه این ارزیابی توسط
تابع سیستمیsys_delete_module
که
در linux/module.c
تعریف
شده است بـــرای شمـــا انــجــام
میشـــود.
شـمــا
نمیتوانید از این تابع بــه طور مستقیم
استفــاده نمایید امــا توابعی در
<linux/modules.h>
تعریف
شده است که اجازه افزایش، کاهش و مشاهده
این شمارنده را میدهد.
به
عنوان مثال:
try_module_get(THIS_MODULE)
که یک
واحد شمارنده را زیاد میکند و
try_module_get(THIS_MODULE)
که یک
واحد شمارنده را کاهش میدهد.
نکته
بسیار مهم این است که مقدار این شمارنده
بایستی همیشه صحیح نگه داشته شود.
اگر
این مقدار خراب شود به هیچ عنوان نمیتوان
ماژول را unload
کرد.
در
این مرحله هیچ کاری به جز reboot
نمیتوان
کرد.
خلاصه
:
در
قسمت پیش و ایــن قسمت با دو ساختــار
داده file_operations
و
file
و
اهمیت آنها آشنــا شــدیـم و نحوه مقدار
دهی آنــها را نیز فرا گرفتیم.
در
ادامه با استفاده از تابع register_chrdev
به
ثبت یک راه انداز در هسته پرداختیم و در
انـتـها به بعضی از نکات در خروج ماژول
از هسته پرداختیم.
در
قسمت اینده یک مثال از یک راه انداز را به
طور کامل بررسی خواهیم کرد.
ترجمه
و تکمیل :
سعید
تقویs.taghavi@ece.ut.ac.ir
PDF Version
منابع
:
1)
http://www.tldp.org/LDP/lkmpg/2.6/html
2)
http://www.linuxhq.com/guides/LKMPG/mpg.html |