设备驱动模型之: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;
}

猜你喜欢

转载自blog.csdn.net/weixin_37867857/article/details/84728805