同样的,在看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; }
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,所以不会创建属性文件。
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链表中。
形成下图的结构。 |