1. 程式人生 > >裝置驅動模型之:kobject,kset,ktype(四)

裝置驅動模型之:kobject,kset,ktype(四)

之前的部落格介紹的關於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;
}