رتبه موضوع:
  • 1 رای - 5 میانگین
  • 1
  • 2
  • 3
  • 4
  • 5
ماژول نویسی برای هسته لینوکس
#11
ماژول نویسی برای هسته لینوکس ( قسمت یازدهم )
ماژول نویسی برای هسته لینوکس ( قسمت یازدهم )

در قسـمت قـــبل بــررسی مدل جدید راه اندازها در هسته لینوکس که به Unified Device Model مــوسوم است را با معرفی چند ساختار داده اصـلی مانند kset , ktype , kobject و subsystem شــروع نمودیم. در این قســـمت به نحوه استفاده از این ساختار های داده در ماژول نویسی هسته لینوکس خواهیم پرداخت. به دلیل حجم بالای مطالب نکات اصلی این توابع مورد بحث وبررسی قرار خواهند گرفت و جزییات بیشتر به خواننده واگذار می شود.




مدیریت kobject ها

با توجه به آنچه در قسمت قبل در مورد kobject ها فرا گرفتیم به بررسی توابعی که مدیریت kobject ها را تسهیل می کنند می پردازیم. ساختار داده kobject معمولا مستقیما به کار نمی رود. بلکه در درون ساختار داده دیگری ( به عنوان مثال cdev که در قسمت قبل آن را بررسی نمودیم ) جاسازی می شود.

اولین قدم در استفاده از kobject هـا تعریف و مقداردهی اولیه آنهاست. این کار با تابع kobject_init انجام می گیرد که در <linux/kobject.h> تعریف شده است.
void kobject_init(struct kobject *kobj);
این تابع kobject ورودی را گرفته و فیلد های آن را مقداردهی می کند. قبل از صدا کردن این تابع بایستی فضای حافظه kobject صفر شود. این کار را می توان با تابع memset انجام داد.
memset(kobj, 0, sizeof (*kobj));
بعد از صفر کردن kobject می توان parent و kset آن را مقدار دهی کرد. به عنوان مثال :
kobj = kmalloc(sizeof (*kobj), GFP_KERNEL);
if (!kobj)
return -ENOMEM;
memset(kobj, 0, sizeof (*kobj));
kobj->kset = kset;
kobj->parent = parent_kobj;
kobject_init(kobj);
بــعداز مــقدار دهی اولیه بایستی نامی برایkobject درنظر گرفته شود.این کار بااستفاده ازتابع ()kobject_set_name انجام می گیرد :
int kobject_set_name(struct kobject * kobj, const char * fmt, ...);
syntax این تابع مانند printk است کــه مـی‌توان آن را بــا fmt بـه صــورت دلخواه نام گذاری کرد. با استفاده از این تابع k_name در ساختار داده kobject مقداردهی می گردد.

بعد از ایجاد یک kobject و مقدار دهی آن شما نیاز دارید که فیــلد‌هــای kset و ktype آن را تنظــیم نمایید. اگر kset نوع kobject را مشخص نکرده باشد تنظیم ktype اجباری می شود در غیر این صورت اختیاری است.







Reference Counts

یکی از امکانات اولیه ای که توسط kobject هــا فراهم شده است مکانیزم یکتایی برای شمارش ارجاعات است. بعد از مقداردهی اولیه مقدار شمارنده ارجاعات kobject به مــقدار ۱ تنظیم می شود. تا زمــانی که این شمارنده صفر نشده است object به حیات خود در حافظه ادامه خواهد داد.

هر کدی که یک ارجاع به object دارد ابتدا یک واحد این شمارنده بالا برده می شود و هنگامی که این کد به پایان رسید یک واحد این شمارنده کاهش می یابد. هنگامی که مقدار این شمارنده به صــفر رســیدobject , از بین رفته و حافظه تخصیص یافته به آن ازاد می شود.

افزایش این شمارنده توسط تابع ()kobject_get انجام می گیرد. این تابع اشاره گری به kobject و در صورت خطا NULL بر می گرداند.
struct kobject * kobject_get(struct kobject *kobj);

متقابلا کاهش این شمارنده توسط تابع ()kobject_put صورت می پذیرد.
void kobject_put(struct kobject *kobj);
اگر شمارنده به صفر برسد تابع release ای که در ktype به آن اشاره شده است صدا زده خواهد شد.







kref

شمارنده kobject توســـط ساختار داده kref که در <linux/kref.h> تعریف شده است و در lib/kref.c پیاده سازی شده است.
struct kref {
atomic_t refcount;
};
تنها فیلد این ساختار داده متغیر refcount است که به صورت atomic تعریف شده و مـــقدار شمارنده را در خود نگه می دارد. قبل از استفاده از kref بایستی آن را با استفاده از ()kref_init مقدار دهی کنید.
void kref_init(struct kref *kref)
{
atomic_set(&kref->refcount, 1);
}
برای گرفتن یک ارجاع ( بالا بردن شمارنده ) از تابع ()kref_get استفاده می شود.
void kref_get(struct kref *kref)
{
WARN_ON(!atomic_read(&kref->refcount));
atomic_inc(&kref->refcount);
}
برای رها کردن یک ارجاع ( پایین اوردن شمارنده ) از تابع ()kref_put استفاده می شود. هنگامی که مقدار شمارنده به صفر رسید تابعی که توسط اشاره گر به تابع release فراهم شده است صدا زده می شود.



void kref_put(struct kref *kref, void (*release) (struct kref *kref))
{
WARN_ON(release == NULL);
WARN_ON(release == (void (*)(struct kref *))kfree);
if (atomic_dec_and_test(&kref->refcount))
release(kref);
}
فایل سیستم [b] sysfs[/b]

فایل سیستم sysfs یک فایل سیستم مجازی در حافظه است که نمایش درختی از kobject ها را برای ما فراهم می کند. این فایل سیستم توپولوژی دستگاه ها را در یک فایل سیستم به ما نمایش می دهد. با استفاده از attribute ها kobject ها می توانند با استفاده از فایل ها این اجازه را بدهند که بتوان بعضی از متغیرهای هسته را خواند و یا در انها نوشت.

اگر چه هــدف ابتدایــی این مدل جدیــد ایجاد یک فرایند کنــتــرل انرژی هوشمند در یک سیستم کامپیوتری بود توسعه دهندگان هسته لینوکس به این نتیجه رسیدند که برای امکانات رفع خطای ساده تر آن را به صورت یک فایل در معرض دیـد بگذارند و sysfs ایجاد شد و به مرور در حال جایگزینی فـــایــل‌های دستگاه‌هـــا در proc/ می‌شــود. امروزه تـــمــام سیستم هایی که از کرنل 2.6 استفاده می کنند فایل سیستم sysfs را به صورت mount شده در سیستم خود دارند.

نمایشی از این فایل سیستم که در mount , /sys شده است را ملاحظه می فرمایید.



[عکس: sysfs.jpg]
شکل ۱- نمایی از فایل سیستم sys/


ریشه این فایل سیستم به طور استاندارد حاوی ۷ دایرکتوری است(در هسته های مختلف ممکن است متفاوت باشد) : block , bus , class , devices , firmware , module , power

دایرکتوری block برای هر دستگاه ( block device ) یـــک دایـــرکتـــوری جـــداگانه دارد. دایرکتوری bus نمایشی از bus سیستم را در خود نگه می دارد. دایرکتوری class نمایشی از دستگاه ها را که توسط توابع سطح بالایی سازمان یافته اند را در بر دارد. دایرکتوری devices نمایشی از توپولوژی دستگاه های موجود در سیستم را در خود نگه می دارد. این دایرکتوری مستقیما به ساختار درختی که از ساختارهای داده ذکر شــــده در هسته تشکیل شده انگاشته می شود. دایرکتوری firmware نیز درختی از اجزای سطح پایین سیستم مانند EFi , EDD , ACPi و ... را نگه می دارد. دایرکتوری های module و power نیز به ترتیب ساختارهایی از ماژول های کرنل و مدیریت انرژی در کرنل را نگه می دارند.

مهمترین دایرکتوری در این فایل سیستم devices است که مدلی از دستگاه های موجود در سیستم را در خود نگه می دارد. تعداد کثیری از فایل های موجود در دایرکتوری های دیگر در حقیقت اشاره گرهایی به فایل های این دایرکتوری هستند. برای اشنایی بیشتر با این فایل سیستم بهتر است ترمینال سیستم گنو/لینوکس خود را باز کرده و چرخی در این فایل سیستم بزنید تا با اجزای آن بیشتر اشنا شوید.







توابع کار با فایل سیستم [b] sysfs[/b]




در این قسمت به دلیل تعداد زیاد توابع , توابع اصلی به صورت تیتروار مورد بررسی قرار می گیرند. برای جزییات بیشتر به کتاب ها یا مقالات اشنایی با هسته لینوکس ( مانند منابع انتهای مقاله ) مراجعه کنید.

kobject هایی که مقدار اولیه داده شده اند به طور اتوماتیک به این فایل سیستم اضافه نمی شوند. برای این کار از تابع kobject_add استفاده می شود. مکان این فایل در این فایل سیستم از موقعیت kobject در ساختار درختی خود تعیین می شود. با استفاده از تابع ()kobject_register می توان دو عمل kobject_init و kobject_add را به یکباره انجام داد. برای حذف نمایشkobject درsysfs ازتابعkobject_dell استفاده می شود. تابع kobject_unregister ترکیبی از دو تابع kobject_dell و kobject_put می باشد.

kobject ها به دایرکتوری ها در sysfs نگاشته می شوند. برای نگاشتن فایل ها به sysfs از فیلد attribute موجود در kobject ها و ktype ها استفاده می شود. ساختار داده attribute در <linux/sysfs.h> تعریف شده و به صورت زیر می باشد:
struct attribute {
char *name; /* attribute's name */
struct module *owner; /* owning module, if any */
mode_t mode; /* permissions */
};
فیلدهای owner , name و mode به ترتیب بیانگر نام , صاحب و سصح دسترسی فایل موجود در sysfs می باشد.

همان طور که در قسمت قبل در بخش ktype گفتیم رفتار پیش فرض دسته ای از kobject ها در ساختار ktype در فیلد default_attrs قرار می گیرد. ولی با استفاده از فیلد sysfs_ops در همین ساختار داده می توان رفتار های kobject را مشخص کرد.
struct sysfs_ops {
/* method invoked on read of a sysfs file */
ssize_t (*show) (struct kobject *kobj,
struct attribute *attr,
char *buffer);
/* method invoked on write of a sysfs file */
ssize_t (*store) (struct kobject *kobj,
struct attribute *attr,
const char *buffer,
size_t size);
};
به طور خلاصه متد ()show برای خواندن به کار می رود. این تابع مقدار attr را در بافری به نام buffer کپی می کند. متد ()store نیز برای نوشتن به کار می رود. این تابع به اندازه size از buffer می خواند و در attr می نویسد. روش ذکر شده برای دسته ای از kobject ها کارایی دارد. برای تنظیم attribute برای یک kobject از توابع زیر استفاده می شود:


int sysfs_create_file(struct kobject *kobj, const struct attribute *attr);
int sysfs_create_link(struct kobject *kobj, struct kobject *target, char *name);
void sysfs_remove_file(struct kobject *kobj, const struct attribute *attr);
void sysfs_remove_link(struct kobject *kobj, char *name);
نتیجه گیری: در این دو قسمت اخیر با مدل جدیدی از دستگاه ها موسوم به sysfs and kobjects اشنا شدیم. ساختار های داده ای مانند kref , ktype , attribute , subsystem , kset و ... را مورد بررسی قرار دادیم و با روش های متفاوتی نحوه استفاده و مدیریت kobject ها و نحوه نمایش انها در sysfs را بررسی کردیم. مطالبی که در این دو قسمت بررسی شدند از جدیدترین موضوعاتی هستند که در هسته لینوکس مورد پیاده سازی قرار گرفته اندو به نظر می رسد که اشنایی هر توسعه دهنده هسته با این مبانی کاملا ضروری می نماید. مطالب این مدل جدید را در همین جا به پایان می بریم و یادگیری جزییات بیشتر را به خواننده واگذار می کنیم. در قسمت اینده به ادامه بحثمان در ماژول نویسی هسته لینوکس خواهیم پرداخت و مطالبی چون کار با توابع سیستمی را مورد بررسی قرار می دهیم.
منبع

[عکس: <a href=www.Mojsazan.com.gif]" class="mycode_img" />
پاسخ
سپاس شده توسط
#12
ماژول نویسی برای هسته لینوکس - قسمت چهاردهم و پایانی
ماجول نویسی برای هسته لینوکس (قسمت چهاردهم و پایانی)

در این قسمت با بررسی چند موضوع باقیمانده مجموعه مقالات اشنایی با ماجول نویسی هسته لینوکس را به پایان می بریم. در ابتدا با دو مثال دو راه ساده ارتباط هسته با دنیای بیرون را شرح خواهیم داد. سپس با نحوه زمان بندی کارها در هسته اشنا خواهیم شد و در ادامه روتین های رسیدگی کننده به وقفه ها (Interrupt Handlers) را مورد بررسی قرار خواهیم داد. در انتها نیز با ذکر چند نکته و جمع بندی این مجموعه مقالات را به پایان خواهیم برد.
تعویض printk
در این بخش نحوه فرستادن پیغام ها از طرف ماجول هسته به tty ها را بررسی خواهیم کرد. این کار با استفاده از متغیر current که اشاره گری به پروسه در حال اجرا است صورت می پذیرد. با استفاده از ساختار داده tty مربوط به این پروسه و صدا کردن تابعی که می تواند یک رشته کاراکتر را بر روی tty چاپ کند این کار انجام می گیرد. مثال print_screen.c نحوه انجام این کار را نشان می دهد. کد ان را از [۱] دریافت کنید.
فلاش LED های کیبورد
در بعضی شرایط شما مایلید که از یک راه ساده با دنیای بیرون ارتباط برقرار کنید. روشن و خاموش کردن LED های کیبورد می تواند یکی از این راه ها باشد. این راه یک راه سریع برای جلب توجه و نشان دادن وضعیت سیستم می تواند باشد. LED های کیبورد در هر سخت افزاری وجود دارند, همیشه قابل دیدن هستند, به نصبی یا چیزی مشابه ان احتیاج ندارند و کارکرد ساده تری نسبت به نوشتن در tty یا یک فایل دارند. در این مثال که کد ان را می توانید از ] بدست اورید ماجول هسته کوچکی نوشته شده است که از زمان وارد شدن به هسته تا زمان خارج شدن چراغ های کیبورد شما را خاموش و روشن می کند. (البته این مثال کمی تغییر داده شده تا جذاب تر باشد
زمان بندی کارها
اغلب ما کارهایی داریم که می خواهیم سر زمان مشخصی اجرا شوند. اگر کار ما توسط پروسه ها قابل انجام است ان را در فایل crontab می گذاریم. اگر قرار است این کار توسط هسته انجام شود دو امکان در اختیار داریم: راه اول این است که پروسه موردنظرمان را در crontab بگذاریم و ماجول موردنظر را با استفاده از تابع سیستمی ای که در این پروسه بیدار نماییم. مثلا با باز کردن فایلی ماجولی را بیدار کنیم. همانطور که حدس زده اید این کار کاملا غیر بهینه است. با استفاده از crontab پروسه ای را اجرا می کنیم و فایل اجرایی را به حافظه می اوریم که فقط یک ماجول هسته را بیدار کنیمبه جای این کار می توانیم تابعی ایجاد کنیم که در هر وقفه زمانی (timer interrupt) صدا زده شود. برای انجام این کار ابتدا بایستی کار (task) مورد نظرمان را ایجاد نماییم, ان را در ساختاری به نام workqueue_struct قرار دهیم. در واقع اشاره گری به این تابع در این صف قرار می گیرد. سپس از تابع queue_delayed_work برای قراردادن ان کار در لیست کارهای my_workqueue که لیست کارهایی که در وقفه زمانی بعد اجرا می شوندقرار می دهیمکد مثال sched.c یک نمونه ای از این زمان بندی را نشان می دهد. در این کد کار خاصی در هر وقفه زمانی انجام می شود. برای دریافت این مثال به ] مراجعه کنید
راه انداز وقفه ها (Interrupt Handlers)
مواردی که تاکنون در این مجموعه مورد بررسی قرار دادیم توابعی بودند که به عنوان پاسخی برای پروسه هایی که ان امکانات را درخواست داده بودند نوشته می شدند. به عنوان مثال توابعی برای ارتباط با یک فایل, پاسخی به ()ioctl یا صدا کردن یک تابع سیستمی برای پاسخ به یک درخواست. اما باید توجه داشت که وظیفه هسته تنها پاسخ گویی به درخواست های پروسه ها نیست. یکی دیگر از وظایف مهم هسته ارتباط با سخت افزار های متصل به سیستم است. به طور کلی دو نوع روش کلی ارتباط بین CPU و دیگر سخت افزار های کامپیوتر وجود دارد. روش اول بدین صورت است که CPU به طور متناوب به دستگاه های دیگر سرک کشیده و دستورات لازم را می دهد. در روش دوم دستگاه هر وقت نیاز داشت که با CPU ارتباط برقرار کند ان را خبر می کندروش دوم که اصطلاحا interrupt یا وقفه نامیده می شود, نسبتا پیاده سازی سخت تری نسبت به روش اول دارد بدلیل اینکه راحتی را برای دستگاه ها به همراه می اورد نه CPU. دستگاه های سخت افزاری معمولا حافظه کمی دارند و اگر شما نتوانید در زمان معین اطلاعات انها را بخوانید ان اطلاعات از دست می رونددر لینوکس وقفه های سخت افزاری Interrupt Request) IRQ) نامیده می شوند. IRQ ها دو دسته هستند: کوتاه وبلند. یک IRQ کوتاه زمان کوتاهی دارد لذا در حین این IRQ دیگر قسمت های سیستم متوقف شده و وقفه دیگری پاسخ داده نمی شود. IRQ بلند زمان بیشتری طول می کشد و در طی ان وقفه های دیگری نیز ممکن است اتفاق بیفتد. ( البته این وقفه ها از دستگاه های یکسانی نمی تواند باشد). بنابراین بهتر است که یک راه انداز وقفه به صورت بلند تعریف شودهنگامی که یک وقفه به CPU می رسد, CPU کار خود را متوقف کرده مگر اینکه رسیدگی به وقفه جاری مهم تر از رسیدگی به وقفه رسیده باشد, در این صورت اجرای وقفه رسیده تا زمانی که وقفه مهم تر تمام شود به تاخیر می افتد), پارامترهای معینی در حافظه پشته (stack) ذخیره و تابع رسیدگی کننده به وقفه صدا زده می شوداین بدان معنی است که بعضی کارهای معین حق اجرا شدن در تابع رسیدگی کننده به وقفه را ندارند بدلیل اینکه سیستم در وضعیت نامشخصی می باشد. راه حل این مساله این است که تابع رسیدگی کننده به وقفه بعضی کارهای لازم را بی درنگ انجام داده که معمولا چیزی از سخت افزار می خواند یا چیزی به ان می فرستد و ادامه کار را در زمان دیگری زمان بندی می کند ( که به این زمان “bottom half” گفته می شود ) و باز می گرددهسته تضمین می کند که ادامه کار را در اولین زمان ممکن انجام دهدمثال زیر نحوه پیاده سازی این رویه را نشان می دهد. کد این مثال را از ] دریافت کنید
جمع بندی مطالب
در این مجموعه از مقالات با مفاهیم کلی و نحوه پیاده سازی بعضی از ماجول های هسته لینوکس اشنا شدیم. در ابتدا مفاهیم کلی را بررسی کردیم. سپس به دستگاه های کاراکتری و ویژگی های انها پرداختیم. با فایل سیستم proc/ به عنوان یکی از راه های ورودی خروجی هسته اشنا شدیم. به بررسی sysfs به عنوان یک متدلوژی هوشمند انرژی در سیستم پرداختیم و با مرور مباحثی چون توابع سیستمی, متوقف کردن پروسه ها, زمان بندی کارها, پاسخ گویی به وقفه ها و ... اشنا شدیم. این مجموعه مسلما فقط در حد اشنایی بوده و تسلط کافی برای طراحی و پیاده سازی ماجول های هسته را به شما نخواهد داد. لذا در ذیل منابعی معرفی شده اند که با مطالعه انها می توانید این تسلط لازم را کسب نمایید
1- Linux Kernel Source Code [5]
2- Linux Kernel Documentation ( Linux Source Code/Documentations )
3- Understanding the Linux Kernel,2nd edition, O'Reilly.
4- Linux Kernel Development, Sams publishing
5- Linux Device Drivers, 3rd edition, O'Reilly.
6-List of Kernel Resources [6]
امید است که این مجموعه مقالات برای علاقه مندان به هسته و سیستم عامل لینوکس مفید بوده باشد. اگر روزی ان قدر در ماژول نویسی هسته لینوکس مهارت کسب نمودید و توانستید ماژول های مفید بنویسید, امیدوارم آنها را با مجوز GPL منتشر کنید تا همه بتوانند باآزادی کامل از ان استفاده نمایند
[عکس: <a href=www.Mojsazan.com.gif]" class="mycode_img" />
پاسخ
سپاس شده توسط
#13
(03-06-2012, 03:15 PM)مهرداد عباسی نوشته: ماژول نویسی برای هسته لینوکس (قسمت اول)


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

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

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



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

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

  1. ۱) نام ماژول مانند 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 از هسته خارج شده است.در قسمت های بعدی با مثال های بیشتر به دیگر جزئیات ماژول نویسی برای هسته لینوکس خواهیم پرداخت.


سلام
ببخشید در مرحله ای که گفتید فایل Makefile بسازیم و دستورات را در آن بنویسیم بیشتر توضیح میدهید ؟
این فایل در کجا قرار می گیرد ؟ ممنون میشم راهنمایی کنید و در مورد محوه کامپیل هم توضیح بیشتر بدهید.
متشکر
پاسخ
سپاس شده توسط
#14
سلام

ممنون اشاره کردید لینک تصحیح شد برای قسمت Makefile
https://www.kernel.org/doc/Documentation...odules.txt

است اگر با Make file  ها آشنایی ندارید

http://www.mojsazan.com/forum/showthread.php?tid=1574

موفق باشید
[عکس: <a href=www.Mojsazan.com.gif]" class="mycode_img" />
پاسخ
سپاس شده توسط digicom
#15
(03-31-2014, 08:48 AM)مهرداد عباسی نوشته: سلام

ممنون اشاره کردید لینک تصحیح شد برای قسمت Makefile
https://www.kernel.org/doc/Documentation...odules.txt

است اگر با Make file  ها آشنایی ندارید

http://www.mojsazan.com/forum/showthread.php?tid=1574

موفق باشید
سلام آقای عباسی
ببخشید من کلا تو همون قسمت فقط مشکل دارم، اگر امکانشه هست توضیح دهید برای ساخت makefile چه باید کرد؟
یک مقاله ای دیگر میخواندم مراحلی که برای سیستم کال نوشته بود خیلی بیشتر از مراحل شما بود.
ممنون میشم مشکل بنده را در آن قسمت رفع کنید.
با نهایت سپاس
پاسخ
سپاس شده توسط


موضوعات مشابه ...
موضوع نویسنده پاسخ بازدید آخرین ارسال
  دانلود کتاب آموزش زبان برنامه نویسی برای سیستم های آندروید مهرداد عباسی 1 5,750 12-04-2013, 12:45 PM
آخرین ارسال: harry_persian138
  شبیه wdk در ویندوز در لینوکس mahmood0197 1 3,979 03-06-2012, 04:08 PM
آخرین ارسال: مهرداد عباسی
  برنامه نویسی موبایل در لینوکس مهرداد عباسی 2 5,801 01-02-2012, 02:49 PM
آخرین ارسال: مهرداد عباسی
  Scala؛ جدیدترین زبان برنامه نویسی آندروید مهرداد عباسی 0 3,544 12-10-2011, 01:41 PM
آخرین ارسال: مهرداد عباسی
  کامپایلر GCC برای اندروید مهرداد عباسی 0 4,718 12-10-2011, 01:37 PM
آخرین ارسال: مهرداد عباسی
  اسکریپت نویسی در اندروید مهرداد عباسی 0 3,831 12-10-2011, 01:35 PM
آخرین ارسال: مهرداد عباسی
  برنامه نویسی با Android NDK مهرداد عباسی 0 6,517 12-10-2011, 01:32 PM
آخرین ارسال: مهرداد عباسی
  دانلود c4droid: کامپایلر c/c++ برای سیستم عامل اندروید + GCC plug-in مهرداد عباسی 0 8,831 12-10-2011, 01:30 PM
آخرین ارسال: مهرداد عباسی
  شروع کار برای برنامه نویسی اندروید مهرداد عباسی 0 4,695 12-10-2011, 01:27 PM
آخرین ارسال: مهرداد عباسی
  می خواهم برای اندروید برنامه بنویسم؟!(قسمت 1) مهرداد عباسی 0 4,068 12-10-2011, 01:26 PM
آخرین ارسال: مهرداد عباسی

پرش به انجمن:


کاربران در حال بازدید این موضوع: 1 مهمان