裝置驅動模型之:kobject,kset,ktype(四)
阿新 • • 發佈:2018-12-08
之前的部落格介紹的關於kobject的一些操作和函式的用法,此篇部落格介紹關於kset函式的一些操作,順便把有關於kset的kobject函式的一些用法補齊,這樣才會有知識共享的效果;
關於kset的操作的函式以及操作的作用有以下:
1. extern void kset_init(struct kset *kset); 關於kset初始化的操作,主要初始化如下: (1)初始化kobject的kref,entry,state_initialized (2) 初始化kset自旋鎖,初始化kset的連結串列 2.extern int __must_check kset_register(struct kset *kset); kset函式組冊進入核心,在kset函式註冊進入核心過程中,會先執行kset_init操作,然後新增kset->kobj的/sys/下的資料夾,最後執行kset_uevent函式,此函式主要是執行根kset下的uevent_ops; 什麼是根kset下的uevent_ops? 在核心中使用如下: while (!top_kobj->kset && top_kobj->parent) top_kobj = top_kobj->parent; 可以看到是最後一個kset->kob的parent的kset不為空的情況下的uevent_ops; 注意: 在kset註冊進入核心過程中,需要將kset->kobj->name賦予值,如果需要則需要將kset->kobj->kset賦予值,如果需要則將kset->uevent_ops賦予值;其中將kset->kobj->name賦予值是必須的操作; 3.extern void kset_unregister(struct kset *kset); 將kset登出出核心,前提是kset->kobj->kref計數為0; 4.extern struct kset * __must_check kset_create_and_add(const char *name, const struct kset_uevent_ops *u, struct kobject *parent_kobj); 此操作是申請一段記憶體並且初始化,把kset->kobj->name賦予name,將kset->uevent_ops賦予u,並且將kset->kobj->parent賦予parent_kobj; 總體和kset_register是一致的,更加簡化了而已;
下面是對於kset_init/kset_register/kset_unregister/kset_create_and_register的詳細解釋;
kset_init函式介面:
函式原型:
extern void kset_init(struct kset *kset);
函式引數:
struct kset* kset,要初始化的kset例項;
函式作用:
初始化kset->kobject例項,主要初始化kset->kobj->entry/state_initialized/kref;
初始化kset->list/list_lock操作;
kset_init函式:
void kset_init(struct kset *k)
{
kobject_init_internal(&k->kobj);
INIT_LIST_HEAD(&k->list);
spin_lock_init(&k->list_lock);
}
kset_register函式介面:
函式原型: int kset_register(struct kset *k) 函式引數: struct kset*k;要註冊進入核心的kset結構體指標例項; 函式作用: 1.向核心註冊kset->kobj例項,主要呼叫kobject_init_internel函式向核心註冊進入kset->kobj; 2.呼叫kset_uevent使用父kset的uevent_ops; 使用注意事項: 1.使用kset_register時候主要是在沒有使用kset_init時候,但是這時候kset->kobj->name還沒有設定,需要在使用此函式之前設定; 2.使用kset_register時候如果此kset還包括在另外一個kset下,在此函式之前需要手動設定kset->kobj->kset指標; 3.使用kset_register時候如果本kset有自己的ktype則需要手動設定,並且初始化;
kset_register函式:
int kset_register(struct kset *k)
{
int err;
if (!k)
return -EINVAL;
kset_init(k);
err = kobject_add_internal(&k->kobj);//向核心中增加kobj
if (err)
return err;
kobject_uevent(&k->kobj, KOBJ_ADD);//使用kset->uevent_ops;
return 0;
}
kset_unregister函式:
函式原型:
void kset_unregister(struct kset *k)
函式引數:
struct kset*k要向核心中登出的kset;
函式作用:
通過呼叫kobj_put(kset->obj),使kset引用計數減一,如果減少到0,則呼叫kset->kobj->ktype->release對於kset釋放操作(如果有定義的話);
void kset_unregister(struct kset *k)
{
if (!k)
return;
kobject_put(&k->kobj);
}
kset_create_and_add函式:
函式原型:
struct kset *kset_create_and_add(const char *name,
const struct kset_uevent_ops *uevent_ops,
struct kobject *parent_kobj)
函式引數:
const char * name要建立的kset->kobj的名字;
const struct kset_uevent_ops * uevent_ops;
kset->uevent_ops指標指向的地方;
stuct kobject * parent_kobj;
kset->kobj->parent指向的父kobject;
函式作用:
1.通過kmalloc申請一段kset,並且初始化,把kset->kobj->parent指向parent_kobj,
把kset->uevent_ops指向uevent_ops,把name賦予kset->kobj->name指標;
2.把預設的kset->kobj->ktype指標賦予全域性的kset_type指標,注意:在此之後不能隨意更改kset->kobj->ktype,否則,會出現一系列的操作性問題;
3.呼叫kset_register向核心註冊;
kset_create_and_add
struct kset *kset_create_and_add(const char *name,
const struct kset_uevent_ops *uevent_ops,
struct kobject *parent_kobj)
{
struct kset *kset;
int error;
/***向核心申請記憶體並且初始化kset,賦予相應的指標**/
kset = kset_create(name, uevent_ops, parent_kobj);
if (!kset)
return NULL;
error = kset_register(kset);//向核心註冊進入kset;
if (error) {
kfree(kset);
return NULL;
}
return kset;
}