Linux設備模型的基礎框架是基於 kobject, kset 和 kobj_type 三個基礎數據結構實現的。這篇主要分析這三個基礎數據結構的做用,以及相互之間的關係。node
1,kobject:數據結構
struct kobject {
const char *name; // 該kobject的名字,用於 sysfs 文件系統下的文件夾名字
struct list_head entry; // 同類型 kobject 鏈表節點
struct kobject *parent; // 指向父節點 kset 的 kobject
struct kset *kset; // 同類型kobject的集合
struct kobj_type *ktype; // kobject的屬性操做方法,以及 release 方法
struct kernfs_node *sd; /* sysfs directory entry */ // 該 kobject 在sysfs文件系統下的節點
struct kref kref; // 引用計數
#ifdef CONFIG_DEBUG_KOBJECT_RELEASE
struct delayed_work release;
#endif
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 是最基礎的數據結構,從上述字段定義中,能夠看出這個結構包含以下功能:dom
(1)引用計數功能。一個kobject可能表明一個總線,設備或驅動等,這些實例在內核空間可能會被多個調度實體或對象指針引用,所以用一個引用計數結構 kref 來記錄當前有多少對象引用該 kobject,當 kref 的引用計數減爲0時,內核接口自動調用用戶指定的release接口銷燬該kobject對象。kref 數據結構的本質就是一個atomic類型的對象,內核提供了 kref_get() 和 kref_put() 兩個接口用於對引用計數自增和自減:ui
struct kref {
refcount_t refcount;
};atom
typedef struct refcount_struct {
atomic_t refs; // 本質上就是一個 atomic 類型的字段
} refcount_t;spa
接口:指針
static inline void kref_get(struct kref *kref)
{
refcount_inc(&kref->refcount); // kref 自增
}對象
static inline int kref_put(struct kref *kref, void (*release)(struct kref *kref))
{
if (refcount_dec_and_test(&kref->refcount)) { // kref 自減
release(kref); // 若是減完以後爲0,釋放該 kref 對象
return 1;
}
return 0;
}blog
(2)鏈表組織結構功能。多個kobject對象連接在一個kset下,造成一個循環雙向鏈表。字段entry是雙向鏈表節點,kset指向該kobject所屬的kset,parent通常指向kset中的kobject。
(3)sysfs接口。一個kobject表示sysfs文件系統中的一個目錄,方便用戶在用戶態訪問內核態數據結構。字段sd表示該kobject在sysfs中的入口項,name表示kobject表示的目錄名稱,ktype表示該目錄的操做接口,包含kobject對象的release接口,以及該目錄下屬性文件的讀寫接口。
2,kset:
struct kset {
struct list_head list; // 用於鏈接該kset下全部kobject的鏈表節點
spinlock_t list_lock;
struct kobject kobj; // 一個kset本質上也是一個 kobject
const struct kset_uevent_ops *uevent_ops; // 內核事件上報用戶態接口,通常用於驅動的熱插拔事件上報
} __randomize_layout;
一個kset表示全部同類型的kobject的集合。kset內部經過包含一個kobject,用來同其下掛的全部kobject組成一個雙向循環鏈表。同時其下掛的全部kobject的parent都指向kset中包含的這個kobject。uevent_ops是內核事件上報用戶態機制,多用於設備和驅動的熱插拔事件上報。
3,kobj_type:
struct kobj_type {
void (*release)(struct kobject *kobj); // 同類型kobject對象的釋放接口
const struct sysfs_ops *sysfs_ops; // kobject屬性文件的讀寫接口
struct attribute **default_attrs; // kobject的屬性
const struct kobj_ns_type_operations *(*child_ns_type)(struct kobject *kobj);
const void *(*namespace)(struct kobject *kobj);
void (*get_ownership)(struct kobject *kobj, kuid_t *uid, kgid_t *gid);
};
一個kobj_type主要用來定義kobject的屬性文件的讀寫接口,以及kobject對象的釋放操做。
2,經過上述分析,咱們能夠畫出 kobject,kset 和 kobj_type之間的關係:
3,總結一下:kobject/kset一般用於其餘對象結構的內置結構,如設備和驅動數據結構一般都包含一個kobject結構,實現引用計數,設備層次結構和sysfs操做等。