之前的博客介绍的关于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;
}