Kernel 設備模型基礎框架kobject

    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操做等。

相關文章
相關標籤/搜索