Kobject 是Linux 2.6 引入的新的設備管理機制,在內核中由struct kobject數據結構進行描述通過這個數據結構使所有設備在底層都具有統一的接口,kobject提供基本的對象管 理,是構成Linux2.6設備模型的核心結構,它與sysfs文件系統緊密關聯,每個在內核中注 冊的kobject對象都對應於sysfs文件系統中的一個目錄。Kobject是組成設備模型的基本結 構。但是,它比較低調,從不單獨使用,都是嵌套在別的數據結構中。類似於C++中的基 類,它嵌入於更大的對象的對象中–所謂的容器–用來描述設備模型的組件。如bus, devices, drivers 都是典型的容器。這些容器就是通過kobject連接起來了,形成了 一個樹狀結構。這個樹狀結構就與/sys相對應。
kobject 結構為一些大的數據結構和子系統提供了基本的對象管理,避免了類似機能的重 復實現。這些機能包括
Kobject結構定義為:
struct kobject { const char *name; struct list_head entry; struct kobject *parent; struct kset *kset; struct kobj_type *ktype; struct sysfs_dirent *sd; struct kref kref; unsigned int state_initialized:1; unsigned int state_in_sysfs:1; unsigned int state_add_uevent_sent:1; unsigned int state_remove_uevent_sent:1; unsigned int uevent_suppress:1; };
其中,重要的變量已經加了注釋,這裡再簡要介紹一下:
kobject對象被關聯到一種特殊的類型,即ktype。 ktype由kobj_type結構體表示,定義於 <linux/kobject.h>中:
struct kobj_type { void (*release)(struct kobject *kobj); struct sysfs_ops *sysfs_ops; struct attribute **default_attrs; };
指向一個attribute結構體數組。這些結構體定義了該 kobject相關的默認 屬性。屬性給定了對象的特征,如果該kobject被導出到sysfs中,那麼這些屬性都將相應 的作為文件而導出。其定義如下:
struct attribute { const char *name; struct module *owner; mode_t mode; };
其中name字段提供了該屬性的名稱,最終出現在sysfs中的 文件名就是它。owner字段在存 在所屬模塊的情況下指向其所屬的module結構體。如果一個模塊沒有該屬性,那麼該字段 為NULL。mode字段類型為modet,他表示sysfs中該文件的權限。
該數據結構以文件的形式輸出到sysfs的目錄當中。在 kobject對應的目錄下面。文件 名就是name。文件讀寫的方法對應於kobj_type中的sysfs_ops。
指向sysfs操作表和一個sysfs文件系統缺省屬性列表,定 義如下:
struct sysfs_ops { ssize_t (*show)(struct kobject *, struct attribute *, char *); ssize_t (*store)(struct kobject *, struct attribute *, const char *, size_t); };
Sysfs操作表包括兩個函數store()和show()。
當用戶態讀取屬性時,show()函數被調 用,show()方法在讀操作時被調用。它會拷貝由 attr提供的屬性值到buffer指定的緩沖區,緩沖區大小為PAGESIZE字節;該 函數若執 行成功,返回寫入buffer的字節數,失敗,返回負的錯誤碼。
kset是kobject對象的集合體。把它看 成一個容器,可將所有相關的kobject對象,比 如“全部的塊設備”置於同一位置。其最重要的作用是建立上層(sub-system)和下層的(kobject)的關聯性。
kobject 也會利用它了分辨自已是屬於那一個類型,然後在/sys 下建立正確的目錄位置。而kset 的優先權 比較高,kobject會利用自已的*kset 找到自已所屬的kset,並把*ktype 指定成該kset下 的ktype,除非沒有定義kset,才會用ktype來建立關系。
Kobject通過kset組織成層次化的結 構,kset是具有相同類型的kobject的集合,在內核中 用kset數據結構表示,定義為:
struct kset { struct subsystem * subsys; 所在的subsystem的指針 struct kobj type * ktype; 指向該kset對象類型描述符的指針 struct list head list; 用於連接該kset中所有kobject的鏈表頭 struct kobject kobj; 嵌入的kobject,用於計數,並被因為父類 struct kset hotplug ops * hotplug ops; 指向熱插拔操作表的指針 };
其中:
kobject對象的parent域均 指向這個內嵌的對象。
函數分別實現將指定keset 對象加入設備層次和從其中刪除;
如果說kset 是管理kobject 的集合,那麼,subsystem 就是管理kset 的集合。 它描述系統中某一類設備子系統,如block subsys表示所有的塊設備,對應於sysfs文件系統中的 block目錄。類似的,devices subsys對應於sysfs中的devices目錄,描述系統中所有的 設備。Subsystem由struct subsystem數據結構描述,定義為:
struct subsystem { struct kset kset; 內嵌的kset對象 struct rw semaphore rwsem; 互斥訪問信號量 };
可以看出,subsystem 與kset的區別就是多了一個信號量,所以在後來的代碼中,subsystem已經完全被kset取締了。
每個kset屬於某個 subsystem,通過設置kset結構中的subsys域指向指定的subsystem可以 將一個kset加入到該subsystem。所有掛接到同一subsystem的kset共享同一個rwsem信號 量,用於同步訪問kset中的鏈表。
subsystem有一組類似 的函數,分別是:
void subsysteminit(struct subsystem *subsys);
int subsystemregister(struct subsystem *subsys);
void subsystemunregister(struct subsystem *subsys);
struct subsystem *subsysget(struct subsystem *subsys)
void subsysput(struct subsystem *subsys);
sysfs文件系統是一個處於 內存中的虛擬文件系統,它為我們提供了kobject對象層次結 構的視圖。幫助用戶可以一個簡單文件系統的方式來觀察系統中各種設備的拓撲結 構。借助屬性對象,kobject可用導出文件的方式,將內核變量提供給用戶讀取或 寫入。
sysfs的訣竅是把 kobject對象與目錄項緊密聯系起來,這點是通過kobject中的 dentry(directory entry)字段實現的。前面提到,dentry結構體表示目錄 項,通過連接kobject到指定的目錄項上,無疑方便的將kobject映射到該目錄上。 好了,kobject其實已經形成了一棵樹了——就是我們心愛的對象模型體系。
sysfs的根目錄下包含了七 個子目錄:block、bus、class、devices、firmware、 module和power。block目錄下的每個子目錄都對應著系統中的一個塊設備。反過 來,每個目錄下又都包含了該塊設備的所有分區。bus目錄提供了一個系統總線視 圖。class目錄包含了以高層功能邏輯組織起來的系統設備視圖。devices目錄是 系統中設備拓撲結構視圖,它直接映射出了內核中設備結構體的組織層次。 firmware目錄包含一些諸如ACPI、EDD、EFI等低層子系統的特殊樹。power目錄包 含了系統范圍的電源管理數據。
僅僅初始化一個kobject 是不能自動將其導出到sysfs中的,想要把kobject導入 sysfs,需要用到函數kobjectadd():
int kobject_add(struct kobject *kobj);
kobject在sysfs中 的位置取決於kobject在對象層次結構中的位置。如果kobject 的父指針被設置,那麼在sysfs中kobject 將被映射為其父目錄下的子目錄,如果 parent沒有設置,那麼kobject將被映射到kset->kobj中的子目錄。兩者都未設 置,映射為 sysfs下的根級目錄。
我們已經看到kobject被 映射為文件目錄,而且所有的對象層次結構都優雅的、一 個不少的映射成為sys下的目錄結構。但是裡面的文件是什麼?sysfs僅僅是一個 漂亮的樹,但是沒有提供實際數據的文件。