> Linux教程 > linux基础 >

linux设备模型之kset

同样的,在看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;

}

 

  1. 在/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,所以不会创建属性文件。

  1. 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链表中。

形成下图的结构。

 

(责任编辑:IT)