ماژول نویسی برای هسته لینوکس ( قسمت یازدهم )(1981 مجموع کلمات موجود در متن) (5932 بار مطالعه شده است)
ماژول نویسی برای هسته لینوکس ( قسمت یازدهم )
در قسـمت قـــبل بــررسی مدل جدید راه اندازها در هسته لینوکس که به 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);
}
فایل
سیستم sysfs
فایل
سیستم sysfs
یک
فایل سیستم مجازی در حافظه است که نمایش
درختی از kobject
ها
را برای ما فراهم می کند.
این
فایل سیستم توپولوژی دستگاه ها را در یک
فایل سیستم به ما نمایش می دهد.
با
استفاده از attribute
ها
kobject
ها
می توانند با استفاده از فایل ها این اجازه
را بدهند که بتوان بعضی از متغیرهای هسته
را خواند و یا در انها نوشت.
اگر
چه هــدف ابتدایــی این مدل جدیــد ایجاد
یک فرایند کنــتــرل انرژی هوشمند در یک
سیستم کامپیوتری بود توسعه دهندگان هسته
لینوکس به این نتیجه رسیدند که برای
امکانات رفع خطای ساده تر آن را به صورت
یک فایل در معرض دیـد بگذارند و sysfs
ایجاد
شد و به مرور در حال جایگزینی فـــایــلهای
دستگاههـــا در proc/
میشــود.
امروزه
تـــمــام سیستم هایی که از کرنل 2.6
استفاده
می کنند فایل سیستم sysfs
را
به صورت mount
شده
در سیستم خود دارند.
نمایشی
از این فایل سیستم که در mount
, /sys شده
است را ملاحظه می فرمایید.
شکل
۱-
نمایی
از فایل سیستم sys/
ریشه
این فایل سیستم به طور استاندارد حاوی ۷
دایرکتوری است(در
هسته های مختلف ممکن است متفاوت باشد)
: block , bus , class , devices , firmware , module , power
دایرکتوری
block
برای
هر دستگاه (
block device ) یـــک
دایـــرکتـــوری جـــداگانه دارد.
دایرکتوری
bus
نمایشی
از bus
سیستم
را در خود نگه می دارد.
دایرکتوری
class
نمایشی
از دستگاه ها را که توسط توابع سطح بالایی
سازمان یافته اند را در بر دارد.
دایرکتوری
devices
نمایشی
از توپولوژی دستگاه های موجود در سیستم
را در خود نگه می دارد.
این
دایرکتوری مستقیما به ساختار درختی که
از ساختارهای داده ذکر شــــده در هسته
تشکیل شده انگاشته می شود.
دایرکتوری
firmware
نیز
درختی از اجزای سطح پایین سیستم مانند
EFi
, EDD , ACPi و
...
را
نگه می دارد.
دایرکتوری
های module
و
power
نیز
به ترتیب ساختارهایی از ماژول های کرنل
و مدیریت انرژی در کرنل را نگه می دارند.
مهمترین
دایرکتوری در این فایل سیستم devices
است
که مدلی از دستگاه های موجود در سیستم را
در خود نگه می دارد.
تعداد
کثیری از فایل های موجود در دایرکتوری
های دیگر در حقیقت اشاره گرهایی به فایل
های این دایرکتوری هستند.
برای
اشنایی بیشتر با این فایل سیستم بهتر است
ترمینال سیستم گنو/لینوکس
خود را باز کرده و چرخی در این فایل سیستم
بزنید تا با اجزای آن بیشتر اشنا شوید.
توابع
کار با فایل سیستم sysfs
در
این قسمت به دلیل تعداد زیاد توابع ,
توابع
اصلی به صورت تیتروار مورد بررسی قرار می
گیرند.
برای
جزییات بیشتر به کتاب ها یا مقالات اشنایی
با هسته لینوکس (
مانند
منابع انتهای مقاله )
مراجعه
کنید.
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
را
بررسی کردیم.
مطالبی
که در این دو قسمت بررسی شدند از جدیدترین
موضوعاتی هستند که در هسته لینوکس مورد
پیاده سازی قرار گرفته اندو به نظر می رسد
که اشنایی هر توسعه دهنده هسته با این
مبانی کاملا ضروری می نماید.
مطالب
این مدل جدید را در همین جا به پایان می
بریم و یادگیری جزییات بیشتر را به خواننده
واگذار می کنیم.
در
قسمت اینده به ادامه بحثمان در ماژول
نویسی هسته لینوکس خواهیم پرداخت و مطالبی
چون کار با توابع سیستمی را مورد بررسی
قرار می دهیم.
نویسنده:
سعید تقوی
s.taghavi@ece.ut.ac.ir
منابع :
1-R. Love, “Linux Kernel Development”, 2nd ed, Sams Publishing, 2005
2-Linux Source Code/Documentation/filesystems/sysfs.txt
3-Linux Source Code/Documentation/kobject.txt
4-http://lwn.net/Articles/54651
5-http://www.win.tue.nl/~aeb/linux/lk/lk-12.html
PDF Version
</BODY>
</HTML>
|