认识Linux设备驱动模型和Kobject
2.6內(nèi)核增加了一個(gè)引人注目的新特性——統(tǒng)一設(shè)備模型(device model)。設(shè)備模型提供了一個(gè)獨(dú)立的機(jī)制專門來(lái)表示設(shè)備,并描述其在系統(tǒng)中的拓?fù)浣Y(jié)構(gòu);
Linux設(shè)備模型的核心是使用Bus、Class、Device、Driver四個(gè)核心數(shù)據(jù)結(jié)構(gòu),將大量的、不同功能的硬件設(shè)備(以及驅(qū)動(dòng)該硬件設(shè)備的方法),以樹(shù)狀結(jié)構(gòu)的形式,進(jìn)行歸納、抽象,從而方便Kernel的統(tǒng)一管理;
而硬件設(shè)備的數(shù)量、種類是非常多的,這就決定了Kernel中將會(huì)有大量的有關(guān)設(shè)備模型的數(shù)據(jù)結(jié)構(gòu)。這些數(shù)據(jù)結(jié)構(gòu)一定有一些共同的功能,需要抽象出來(lái)統(tǒng)一實(shí)現(xiàn),否則就會(huì)不可避免的產(chǎn)生冗余代碼。這就是Kobject誕生的背景;
通過(guò)parent指針,可以將所有Kobject以層次結(jié)構(gòu)的形式組合起來(lái);
使用一個(gè)引用計(jì)數(shù)(reference count),來(lái)記錄Kobject被引用的次數(shù),并在引用次數(shù)變?yōu)?時(shí)把它釋放(這是Kobject誕生時(shí)的唯一功能);
和sysfs虛擬文件系統(tǒng)配合,將每一個(gè)Kobject及其特性,以文件的形式,開(kāi)放到用戶空間(有關(guān)sysfs,會(huì)在其它文章中專門描述,本文不會(huì)涉及太多內(nèi)容);
Kobject是Linux設(shè)備模型的基礎(chǔ);
回想文件系統(tǒng)中的核心對(duì)象“索引節(jié)點(diǎn)(indoe)”和目錄項(xiàng)“dentry”:
? ? inode—與文件系統(tǒng)中的一個(gè)文件相對(duì)應(yīng)(而實(shí)際上,只有文件被訪問(wèn)時(shí),才在內(nèi)存創(chuàng)建索引節(jié)點(diǎn));
? ? dentry—每個(gè)路徑中的一個(gè)分量,例如路徑/bin/ls,其中/、bin和ls三個(gè)都是目錄項(xiàng),只是前兩個(gè)是目錄,而最后一個(gè)是普通文件;也就是說(shuō),目錄項(xiàng)或者是一子目錄,或者是一個(gè)文件;
既然,kobject要形成一顆樹(shù),那么其中的字段就要有parent,以表示樹(shù)的層次關(guān)系;另外,kobject得有name字段,按說(shuō),目錄或文件名并不會(huì)很長(zhǎng),但是,sysfs文件系統(tǒng)為了表示對(duì)象之間復(fù)雜的關(guān)系,需要通過(guò)軟鏈接達(dá)到,而軟鏈接常常有較長(zhǎng)的名字,通過(guò)以上的分析,目前可以得知kobject對(duì)象包含的字段有:
struct kobject {
? ? char ? ? ? *k_name; ?/*長(zhǎng)名字*/
? ? char ? ? ? name[kOBJ_NAME_LEN]; /* 短名字*/
? ? struct kobject ? ?*parent; /* 表示對(duì)象的層次關(guān)系*/
? ? struct dentry *dentry; /*表示sysfs中的一個(gè)目錄項(xiàng) */
};
查看kobject.h頭文件,看到它還包含以下字段:
struct kobject {
? ? struct kref ? ? ? ? ?kref;
? ? struct list_head ?entry;
? ? struct kset ? ? ? ? ?*kset;
? ? struct kobj_type ?*ktype;
};
這四個(gè)字段,每一個(gè)都是結(jié)構(gòu)體,其中structlist_head是內(nèi)核中形成雙向鏈表的基本結(jié)點(diǎn)結(jié)構(gòu);
增加一個(gè)引用計(jì)數(shù)可通過(guò)koject_get()函數(shù)完成:
? ? struct kobject* kobject_get(struct kobject *kobj);
該函數(shù)正常情況下將返回一個(gè)指向kobject的指針,如果失敗則返回NULL指針;
減少引用計(jì)數(shù)通過(guò)kobject_put()完成:
? ? void kobject_put(struct kobject *kobj);
如果對(duì)應(yīng)的kobject的引用計(jì)數(shù)減少到零,則與該kobject關(guān)聯(lián)的ktype中的析構(gòu)函數(shù)將被調(diào)用;
深入到引用計(jì)數(shù)系統(tǒng)的內(nèi)部去看,會(huì)發(fā)現(xiàn)kobject的引用計(jì)數(shù)是通過(guò)kref結(jié)構(gòu)體實(shí)現(xiàn)的,該結(jié)構(gòu)體定義在頭文件<linux/kref.h>中:
struct kref {atomic_t refcount;};
其中唯一的字段是用來(lái)存放引用計(jì)數(shù)的原子變量。那為什么采用結(jié)構(gòu)體?這是為了便于進(jìn)行類型檢測(cè);
上述的所有函數(shù)定義與聲明分別在在文件lib/kref.c和文件<linux/kref.h>中。
共同特性的ktype
? ? kobject是一個(gè)抽象而基本的對(duì)象。對(duì)于一族具有共同特性的kobject,就是用定義在頭文件<linux/kobject.h>中的ktype來(lái)描述:
struct kobj_type { ? ?
? ? void (*release)(structkobject *);
? ? struct sysfs_ops ?*sysfs_ops;
? ? struct attribute ?**default_attrs;
};
release指針指向在kobject引用計(jì)數(shù)減至零時(shí)要被調(diào)用的析構(gòu)函數(shù),該函數(shù)負(fù)責(zé)釋放所有kobject使用的內(nèi)存和其它相關(guān)清理工作;
sysfs_ops變量指向sysfs_ops結(jié)構(gòu)體,其中包含兩個(gè)函數(shù),也就是對(duì)屬性進(jìn)行操作的讀寫函數(shù)show()和store();
最后,default_attrs指向一個(gè)attribute結(jié)構(gòu)體數(shù)組。這些結(jié)構(gòu)體定義了kobject相關(guān)的默認(rèn)屬性;屬性描述了給定對(duì)象的特征,其實(shí),屬性就是對(duì)應(yīng)/sys樹(shù)形結(jié)構(gòu)中的葉子結(jié)點(diǎn),也就是文件;
?
總結(jié)
以上是生活随笔為你收集整理的认识Linux设备驱动模型和Kobject的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: MongoDB删除数据
- 下一篇: 初步了解Linux创建文件系统命令