/************************************************************************************html
本文爲我的學習記錄,若有錯誤,歡迎指正。node
本文參考資料: 網絡
* https://blog.csdn.net/yyplc/article/details/7465569數據結構
* http://www.javashuo.com/article/p-cqnvxgtk-bw.html函數
* http://www.javashuo.com/article/p-mvsagsdc-m.html學習
* http://www.javashuo.com/article/p-sqivihik-bm.htmlui
************************************************************************************/編碼
kobject是Linux 2.6後引入的新的設備管理機制,在內核中由struct kobject表示。經過這個數據結構使全部設備在底層都具備統一的接口,kobject提供基本的對象管理,是構成Linux2.6設備模型的核心結構。它與sysfs文件系統緊密關聯,每一個在內核中註冊的kobject對象都對應於sysfs文件系統中的一個目錄。spa
kobject是組成設備模型的基本結構。相似於C++中的基類,它嵌入於更大的對象的對象中--所謂的容器--用來描述設備模型的組件。如bus,devices, drivers 都是典型的容器。這些容器就是通kobject鏈接起來了,造成了一個樹狀結構,這個樹狀結構就與/sys相對應。.net
kobject 結構爲一些大的數據結構和子系統提供了基本的對象管理,避免了相似機能的重複實現。這些機能包括
(1) 對象引用計數;
(2)維護對象鏈表(集合);
(3)對象上鎖;
(4)在用戶空間的表示。
struct kobject
{ const char *name; //表示kobject對象的名字,對應sysfs下的一個目錄 struct list_head entry; //是kobject中插入的head_list結構 struct kobject *parent; //指向當前kobject父對象的指針,體如今sys結構中就是包含當前kobject對象的目錄對象 struct kset *kset; //表示當前kobject對象所屬的集合 struct kobj_type *ktype; //表示當前kobject的類型,包含了kobject相關的操做函數和屬性 struct sysfs_dirent *sd; //用於表示VFS文件系統的目錄項,是設備與文件之間的橋樑,sysfs中的符號連接就是經過kernfs_node內的聯合體實現的 struct kref kref; //對kobject的引用計數,當引用計數爲0時,就回調以前註冊的release方法釋放該對象 unsigned int state_initialized:1; //初始化標誌位,在對象初始化時被置位,表示對象是否已經被初始化 unsigned int state_in_sysfs:1; //表示kobject對象在sysfs中的狀態,在對應目錄中被建立則置1,不然爲0 unsigned int state_add_uevent_sent:1; //添加設備的uevent事件是否發送標誌,添加設備時會向用戶空間發送uevent事件,請求新增設備 unsigned int state_remove_uevent_sent:1; //刪除設備的uevent事件是否發送標誌,刪除設備時會向用戶空間發送uevent事件,請求卸載設備 unsigned int uevent_suppress:1; };
Linux內核中提供如下操做kobject的函數。
//kobject初始化函數 void kobject_init(struct kobject * kobj); //設置指定kobject的名稱 int kobject_set_name(struct kobject *kobj, const char *format, ...); //將kobj對象的引用計數加1,同時返回該對象的指針 struct kobject *kobject_get(struct kobject *kobj); //將kobj對象的引用計數減1,若是引用計數降爲0,則調用kobject release()釋放該kobject對象 void kobject_put(struct kobject * kobj); //將kobj對象加入Linux設備層次。掛接該kobject對象到kset的list鏈中,增長父目錄各級kobject的引用計數,在其 parent指向的目錄下建立文件節點,並啓動該類型內核對象的hotplug函數 int kobject_add(struct kobject * kobj); //kobject註冊函數。經過調用kobject init()初始化kobj,再調用kobject_add()完成該內核對象的註冊 int kobject_register(struct kobject * kobj); //從Linux設備層次(hierarchy)中刪除kobj對象 void kobject_del(struct kobject * kobj); //kobject註銷函數。與kobject register()相反,它首先調用kobject del從設備層次中刪除該對象,再調用kobject put()減小該對象的引用計數,若是引用計數降爲0,則釋放kobject對象 void kobject_unregister(struct kobject * kobj);
ktype表示當前kobject的類型,其中包含了kobject相關的操做函數和屬性。
struct kobj_type { void (*release)(struct kobject *kobj); //release方法用於釋放kobject佔用的資源 const struct sysfs_ops *sysfs_ops; //指向sysfs操做表 struct attribute **default_attrs; //sysfs文件系統缺省列表屬性 const struct kobj_ns_type_operations *(*child_ns_type)(struct kobject *kobj); const void *(*namespace)(struct kobject *kobj); };
sysfs操做表包括兩個函數store()和show()。當用戶態讀取屬性 時,show()函數被調用,該函數編碼指定屬性值存入buffer中返回給用戶態;而store()函數用於存儲用戶態傳入的屬性值。詳見Linux設備管理:sysfs文件系統的功能及其應用
struct sysfs_ops { ssize_t (*show)(struct kobject *, struct attribute *,char *); ssize_t (*store)(struct kobject *,struct attribute *,const char *, size_t); };
attribute, 屬性。它以文件的形式輸出到sysfs的目錄當中,在kobject對應的目錄下面。文件名爲name。文件讀寫的方法對應於kobj type中的sysfs ops。
struct attribute { const char *name; struct module *owner; mode_t mode; };
kset最重要的是創建上層(sub-system)和下層的(kobject)的關聯性。
kset表示一組kobject的集合,kobject經過kset組織成層次化的結構,全部屬於該kset的kobjetc結構的parent指針指向kset包含的kobject對象,構成一個父子層次關係。這些kobject能夠是不一樣或相同的類型(kobj_type)。sysfs中的設備組織結構很大程度上都是根據kset進行組織的,好比"/sys/drivers"目錄就是一個kset對象,包含系統中的驅動程序對應的目錄,驅動程序的目錄又由kobject表示。好比在平臺設備模型中,當咱們註冊一個設備或驅動到平臺總線,實際上是將對應的kobject掛接到platform總線的kset上,每種總線都是維護兩條鏈表(兩個kset),一條用於連接掛接在上面的驅動(驅動kset),一條用於連接掛接在上面的設備(設備kset)。
struct kset { struct list_head list; spinlock_t list_lock; struct kobject kobj; const struct kset_uevent_ops *uevent_ops; };
kobject、ktype、kset之間的聯繫以下圖所示。。