1. 程式人生 > >linux驅動基礎知識-白陽(三) KOBJECT引用計數

linux驅動基礎知識-白陽(三) KOBJECT引用計數


kobject主要功能:1,提供裝置的引用計數, 2,提供sysfs支援 3,提供熱插拔機制
kobject 提供了基本的物件管理能力,是構成 Linux 2.6 裝置模型的核心結構,每個在核心中註冊的 kobject 物件都對應於 sysfs 檔案系統中的一個目錄


linux/kobject.h
linux/kerf.h
linux/refcount.h

lib/kobject.c 和lib/kobject_uevent.c; 事件部分以後再看

一、:引用計數-這裡是個原子變數,具有原子的讀寫、設定等
typedef struct refcount_struct {
atomic_t refs;
} refcount_t;


struct kref {
refcount_t refcount; //引用計數 ,原子變數  atomic_t refs;
};

二、當前連結串列節點,用來掛載到kset的部分
struct list_head entry;

三、 struct kobj_type 物件型別 ,與sysfs 掛鉤
struct sysfs_ops {
ssize_t (*show)(struct kobject *, struct attribute *, char *);
ssize_t (*store)(struct kobject *, struct attribute *, const char *, size_t);
};
sysfs_ops 包括 store()和 show()兩個成員函式,用於實現屬性的讀寫
當從使用者空間讀取屬性時, show()函式將被呼叫,該函式將指定屬性值存入 buffer 中返回給使用者; store()函式用於儲存使用者通過 buffer 傳入的屬性值。


kobject 不同的是, 屬性在 sysfs 中呈現為一個檔案,而 kobject 則呈現為 sysfs 中的目錄 ???!!!不太懂

struct kobj_type {
void (*release)(struct kobject *kobj); //釋放 kobject 佔用的資源的 release()函式
const struct sysfs_ops *sysfs_ops; //sysfs_ops 包括 store()和 show()兩個成員函式,用於實現屬性的讀寫

struct attribute **default_attrs; // sysfs 檔案系統預設屬性列表
const struct kobj_ns_type_operations *(*child_ns_type)(struct kobject *kobj);
const void *(*namespace)(struct kobject *kobj);
};


void kobject_init(struct kobject *kobj, struct kobj_type *ktype);
//初始化 引用計數為1和初始化狀態,初始化連結串列頭,初始化ktype型別

四、
kset 具有相同型別的 kobject 的集合,根types來區別
/**
* struct kset - a set of kobjects of a specific type, belonging to a specific subsystem.
*
* A kset defines a group of kobjects. They can be individually
* different "types" but overall these kobjects all want to be grouped
* together and operated on in the same manner. ksets are used to
* define the attribute callbacks and other common events that happen to
* a kobject.
*
* @list: the list of all kobjects for this kset
* @list_lock: a lock for iterating over the kobjects
* @kobj: the embedded kobject for this kset (recursion, isn't it fun...)
* @uevent_ops: the set of uevent operations for this kset. These are
* called whenever a kobject has something happen to it so that the kset
* can add new environment variables, or filter out the uevents if so
* desired.
*/
struct kset {
struct list_head list; //用於連線該 kset 中所有 kobject 的連結串列頭

spinlock_t list_lock;
struct kobject kobj; ///嵌入的 kobject,kset的引用計數就是實際上就是內嵌的 kobject 物件的引用計數
const struct kset_uevent_ops *uevent_ops; //事件操作集
} __randomize_layout;


struct kset_uevent_ops {
int (* const filter)(struct kset *kset, struct kobject *kobj); //事件過濾
const char *(* const name)(struct kset *kset, struct kobject *kobj);
int (* const uevent)(struct kset *kset, struct kobject *kobj,
struct kobj_uevent_env *env); //環境變數設定
};
Linux 提供一系列函式操作 kset。 kset_init()完成指定 kset 的初始化, kset_get()和
kset_put()分別增加和減少 kset 物件的引用計數, kset_add()和 kset_del()函式分別實現將指定 keset 物件
加入裝置層次和從其中刪除, kset_register()函式完成 kset 的註冊, kset_unregister()函式則完成 kset 的
登出。




五、kobject
struct kobject {
const char *name;
struct list_head entry; //kobject用來掛載到kset同類物件的連結串列節點,
struct kobject *parent; //父類kobject,指向所屬kset的kobject
struct kset *kset; //同類kobject的集合

struct kobj_type *ktype; //型別
struct kernfs_node *sd; /* sysfs directory entry */
struct kref kref; //物件引用計數*******原子變數
#ifdef CONFIG_DEBUG_KOBJECT_RELEASE
struct delayed_work release;
#endif
unsigned int state_initialized:1; //初始化時被設定為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;
};
Linux 核心中提供一系列操作 kobject 的函式:
void kobject_init(struct kobject * kobj);
該函式用於初始化 kobject,它設定 kobject 引用計數為1, entry 連結串列初始化

int kobject_set_name(struct kobject *kobj, const char *format, ...);
該函式用於設定指定 kobject 的名稱。
//例如:retval = kobject_set_name(&kset->kobj, "%s", name);


void kobject_cleanup(struct kobject * kobj)和 void kobject_release(struct kref *kref);
該函式用於清除 kobject,當其引用計數為0時,釋放物件佔用的資源。(也就是呼叫ktype中的release方法)

struct kobject *kobject_get(struct kobject *kobj);
該函式用於將 kobj 物件的引用計數加 1,同時返回該物件的指標。

void kobject_put(struct kobject * kobj);
該函式用於將 kobj 物件的引用計數減 1,如果引用計數降為 0,則呼叫 kobject_release()釋放該 kobject物件。

int kobject_add(struct kobject *kobj, struct kobject *parent, kobj_ns_drop const char *fmt, ...)
該函式用於將 kobject 物件加入 Linux 裝置層次,它會掛接該 kobject 物件到 kset 的 list 鏈中,增加父
目錄各級 kobject 的引用計數,在其 parent 指向的目錄下建立檔案節點,並啟動該型別核心物件的 hotplug函式。
建立sysfs檔案

struct kobject *kobject_create_and_add(const char *name, struct kobject *parent)
該函式用於註冊 kobject,它會先呼叫 kobject_init()初始化 kobj,再呼叫 kobject_add()完成該核心物件的新增。
呼叫完成後 ,使用kobject_put會自動釋放記憶體

kobject_del()從裝置層次中刪除該物件,再呼叫 kobject_put()減少該物件的引用計數,如果引用計數降為 0,則釋放該 kobject 物件。

#注:這裡只是自己整理了部分,需要用時看那幾個標頭檔案和實現;或者參考宋寶華老師的《Linux裝置驅動開發詳解》第四章;;