同样的,在看kset-example之前我们先看下kset的相关操作函数。
kobject_set_name 设定kobject的name
这个函数就是前面介绍的kobject_set_name_vargs函数的封装。
kset_init 初始化kset
voidkset_init(struct kset *k)
{
kobject_init_internal(&k->kobj);
INIT_LIST_HEAD(&k->list);
spin_lock_init(&k->list_lock);
}
因为kset结构体中内嵌一个kobject结构体,所以初始化时要初始化kset中内嵌的kobject结构体;然后初始化kset中list双向链表。
kset_create 动态地创建一个kset结构体
staticstruct kset *kset_create(const char *name,
conststruct kset_uevent_ops *uevent_ops,
structkobject *parent_kobj)
给新建的kset结构体分配内存,将kset内嵌的kobject的name设定为constchar *name,
设定几个分量:
kset->uevent_ops= uevent_ops;
kset->kobj.parent= parent_kobj;
kset->kobj.ktype= &kset_ktype;
kset->kobj.kset= NULL;
kset_register 初始化并添加一个kset
intkset_register(struct kset *k)
{
interr;
if(!k)
return-EINVAL;
kset_init(k);
err= kobject_add_internal(&k->kobj);
if(err)
returnerr;
kobject_uevent(&k->kobj,KOBJ_ADD);
return0;
}
下面再来分析kset-example.ko的注册过程:
staticint __init example_init(void)
{
/*
* Create a kset with the name of "kset_example",
* located under /sys/kernel/
*/
example_kset= kset_create_and_add("kset_example", NULL, kernel_kobj); -------a-------
if(!example_kset)
return-ENOMEM;
/*
* Create three objects and register them with our kset
*/
foo_obj= create_foo_obj("foo"); -------b---------
if(!foo_obj)
gotofoo_error;
bar_obj= create_foo_obj("bar"); ---------c---------
if(!bar_obj)
gotobar_error;
baz_obj= create_foo_obj("baz"); ---------d---------
if(!baz_obj)
gotobaz_error;
return0;
baz_error:
destroy_foo_obj(bar_obj);
bar_error:
destroy_foo_obj(foo_obj);
foo_error:
return-EINVAL;
}
在/sys/kernel/目录下新建一个kset_example的文件夹;
struct kset*kset_create_and_add(const char *name,
const structkset_uevent_ops *uevent_ops,
struct kobject*parent_kobj)
{
struct kset *kset;
int error;
kset = kset_create(name,uevent_ops, parent_kobj); ------a1-------------
if (!kset)
return NULL;
error = kset_register(kset); ------a2-------------
if (error) {
kfree(kset);
return NULL;
}
return kset;
}
A1、将kset内嵌的kobject的name设置为kset-example;
kset->uevent_ops= uevent_ops; 这里就是设置为NULL
kset->kobj.parent= parent_kobj; 父kobj指向kernel_kobj,也就是/sys/kernel
kset->kobj.ktype= &kset_ktype;
设置内嵌kobj的ktype为
static struct kobj_typekset_ktype = {
.sysfs_ops =&kobj_sysfs_ops,
.release= kset_release,
};
kset->kobj.kset= NULL;
A2、kset_init(k);初始化k内嵌的kobject并初始化kset的list;
kobject_add_internal(&k->kobj);
创建kset-example的文件夹,因为kset_ktype没有default_attrs,所以不会创建属性文件。
staticstruct foo_obj *create_foo_obj(const char *name)
foo_obj是在kobject结构体之上封装的一个结构体:
struct foo_obj {
struct kobject kobj;
int foo;
int baz;
int bar;
};
B1、新建一个foo_obj结构体
B2、foo->kobj.kset= example_kset; 当一个kobject属于kset时,在调用kobject核心函数前我们先设好kset。
B3、retval= kobject_init_and_add(&foo->kobj, &foo_ktype, NULL, "%s",name);
在kset_example目录下新建了一个foo文件夹,并在foo文件夹下新建三个文件,
文件是与attribute相关的:
static struct attribute*foo_default_attrs[] = {
&foo_attribute.attr,
&baz_attribute.attr,
&bar_attribute.attr,
NULL, /* need to NULL terminatethe list of attributes */
};
新建的三个文件是foo、bar和baz。
Foo->kobj->ktype= foo_ktype
在添加kobject的时候,因为kobject的kset已被设好,而kobject的parent没设好,所以将kobject的parent设为kset内嵌的kobject,并将kobj加入kset的list链表中。
形成下图的结构。