ماژول نویسی برای هسته لینوکس (قسمت هشتم)(667 مجموع کلمات موجود در متن) (7239 بار مطالعه شده است)  ماژول
نویسی برای هسته لینوکس (قسمت
هشتم)
در
قسمت های قبل با اصول و مبانی ماژول نویسی
برای هسته لینوکس آشنا شدیم و ابتدایی
ترین مفاهیم نوعی از دستگاهها موسوم به
دستگاه های کاراکتری را بررسی نمودیم.
در
این قسمت و دو قسمت آینده مطالبمان را با
بررسی فایل سیستم proc/
و
کاربرد آن در ماژول نویسی برای هسته لینوکس
ادامه خواهیم داد.
در
لینوکس مکانیزم ویژهای بـرای هسته و
ماژولهای هسته بــرای ارسال و دریافت
اطلاعـات از پروسسها وجـود دارد که در
قالب فایل سیستم مجازی proc/
پیاده
سازی شده است.
این
فایل سیستم بـرای ســهولت دستـرسی به
اطلاعاتی در زمینه پروسسها طراحی شده
است.
به
عنوان مثــالproc/modules/
لیستی
از مــاژولهای وارد شــده در هـسته و
proc/meminfo/
اماری
از میزان مصرف حافظه را نشان میدهند.
برای
آشنایی بیشتر با این فایل سیستم این
مقاله
[۱]
را
مطالعه بفرمایید.
روشی
که برای استفاده از فایل سیستم proc/
به
کار میرود بسیـار شبـیـه روشـی است که
در مورد راه اندازها به کار میرود، یک
نمونه یا instance
از
struct
ای
که تمامی این اطلاعات را به همراه اشاره
گــرهــایی بـه توابع مورد نظر ایجاد
میگردد.
سپس
در تابع شروع ماژول که همان init_module
است
ایــن سـاخـتـار داده در هسـتـه ثبت شده
و در هنگام اتمام ماژول که cleanup_module
صدا
زده میشود این ساختار داده از هسته خارج
میگردد.
بحثمان
را با یک مثال شروع میکنیم.
کد
این مثال و مثال بعدی را کــه حــاوی
comment
کــاملی
هستند را میتوانید از اینجا
[۲]
بدست
اورید.
با
مثال اول (
فایل
procfs1.c
) شــروع
میکنـیـم.
ایــن
مثال از ۳ قسمت تشکیل شده است:
در
تابع init_moduleفایلproc/helloworld/
ایجــاد
میشـود، هنگامیکه از این فایل خوانده
میشود تابع procfs_read
صدا
زده میشود که یک مقدار (
و
یک بافر )
بر
میگرداند.
در
نهایت در تابع cleanup_module
این
فایل حذف میگردد.
فایل
proc/helloworld/
هنگامیکه
ماژول در هسته وارد میشود توســط تابع
create_proc_entry
ایجاد
میگردد.
مقدار
بازگشتی ایـن تابع یک '*
struct proc_dir_entry' اسـت
کــه بــرای پـیـکـربندی فایل
proc/helloworld/
(به
عنوان مثال تعیین صاحب فایل)
به
کار میرود.
مقدار
بازگشتی NULL
نشان
میدهد که اجرای این تابع ناموفق بوده
است.
هر
هنگام کــه از فایل proc/helloworld/
خوانده
میشود تــابع procfs_read
صدا
زده میشود.
دو
پارامتر ورودی این تابع بسیار مهم هستند.
buffer ( اولین
پارامتر )
و
offset
( سومین
پارامتر ).
محتــوای
بافر به برنامهای کــه تقاضای خواندن
داده است باز میگردد (به
عنوان مثال دستور cat).
پارامتر
offset
نیز
مکان فعلی در فــایــل را نـشـان میدهد.
اگر
مقدار بازگشتی این تابع NULL
نباشد،
این تابع دوباره صدا زده خواهد شد.
بنــابـراین
مراقب این تابع باشید اگر مقدار بازگشتی
این تابع هیجگاه صفر نشود صدا زدن این
تابع به صورت بی پایان ادامه خواهد داشت.
مثالprocfs1.c
را
کامپایل کرده و ماژول تولیدی را در هسته
وارد نمــایـیــد.
بـا
استفاده از دستور زیر از proc/helloworld/
بخوانید
:
#cat
/proc/helloworld
خواندن
از و نوشتن در یک فایل proc/
مثال
قبل که مثال ساده ای از خواندن از یک فایل
proc/
بود
را دیدیم.
نکتهای
کــه میخواهیم در ایــن قســمت بـررسـی
کنیم، نوشتن در یک فایل proc/
است.
هنگام
نوشتن در فایل proc/
مانند
حالت خواندن یک تابع مانند procfs_write
صدا
زده میشود.
اما
تفاوتهایی بیــن خــواندن و نوشتن وجــود
دارد کــه مـهم ترین آن انتقال یافتن
اطلاعات از فضای کاربر به فضای هسته در
حال نوشتن است که این کار توسط توابعی
مانند copy_from_user
یا
get_user
انجام
میشود.
دلیل
وجود توابعی مانند دو تابع بالا این است
که حافظه در لینــوکس (در
معماری پردازنده اینتل، ممکن است در
پردازنده های دیگر متفاوت باشد)
بــه
segment
هایی
تقسیم شده است.
ایــن
بدان معنا است که یک اشاره گر به تنهایی
به ادرس یکتایی در حافظه اشاره نمیکند
,
بلکه
به موقعیتی در segment
اشاره
میکند و شما نیاز داید که segment
حافظه
را بدانید تا بتوانید از ان استفاده کنید.
فقط
یک segment
برای
هسته وجود دارد و برای هر پروسس نیز یک
segment
اختصاص
مییابد.
تنها
segment
ای
که یک پروسس میتواند به ان دسترسی داشته
باشد segment
خود
پروسس است.
بنابراین
هنگامیکه شما برنامهای توسعه میدهید
یا اجرا میکنید، واقعا لازم نیست که
نگران مدیریت segmentهای
حافظه باشید.
امــا
هنـگـامی که یک ماژول هسته مینویسید،
معمــولا میخواهید کــه بــه فضــای
حـافـظه segment
هسته
کــه توسط سیستم راه اندازی میشود دسترسی
داشته باشید.
با
این حال هنگامیکه نیــاز است محتـوای
یک بافر حافظه بین یک پروسس و هسته رد و
بدل شود هسته یــک اشاره گر به بافر حافظه
segment
پروسس
دریافت میدارد.
ماکروهای
put_user
و
get_user
اجازه
دسترسی به این حافظه را میدهند.
این
توابع فقط یک کاراکتر تحویل میدهـند.
شما
میتوانید با استفاده از توابع copy_to_user
و
copy_from_user
کاراکترهای
متعددی را دریافت دارید و یا به هسته تحویل
دهید.
چون
که بافر (در
توابع خواندن و نوشتن)
در
فضای هسته است، برای نوشتن شما نیاز دارید
کــه اطــلاعاتـتـان را import
کنید
اما در تابع خواندن اطلاعات هم اکنون در
فضای هسته است.
برای
جا افتادن مطلب به مثال procfs2.c
مراجعه
کنید.
کد
این مثال را از اینجا
[۲]
میتوانید
بدست آورید.
در
قسمت آینده نحوه مدیریت فایل سیستم مجازی
proc/
را
بررسی خواهیم کرد.

ترجمه
و تکمیل:
سعید
تقوی 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
پانوشتها:
[۱]
/html/modules.php?op=modload&name=Sections&file=index&req=viewarticle&artid=64
[۲]
/files/procfs1-2.tar.bz2
|