uclinux内核的对象表示:kobjects

快乐虾

http://blog.csdn.net/lights_joy/

[email protected]

本文适用于

ADI bf561 DSP

优视科技BV561EVB开发板

uclinux-2008r1.5-rc3 (smp patch)

Visual DSP++ 5.0(update 5)

欢迎转载,但请保留作者信息

内核中使用了kobject来表示与管理一些内核对象,从documentation/kobject的描述可知,kobject兼有以下几个作用:

- Object reference counting.

- Maintaining lists (sets) of objects.

- Object set locking.

- Userspace representation.

kobjectsysfs文件系统有着密切的关系,所有注册到kobject核心的对象都将在sysfs文件系统中拥有一个目录,从而达到导出内核对象的目的。

1.1 相关数据结构

1.1.1 kref

这个结构体的定义位于include/linux/kref.h,用于表示一个kobject对象的引用计数。

struct kref {

atomic_t refcount;

};

就是一个atomic_t类型的数据。

通常使用kref_init函数对它进行初始化:

/**

* kref_init - initialize object.

* @kref: object in question.

*/

void kref_init(struct kref *kref)

{

atomic_set(&kref->refcount,1);

smp_mb();

}

即将refcount的初值设置为1

1.1.2 kobject

这个结构体用于表示一个内核对象,其定义在include/linux/kobject.h

#define KOBJ_NAME_LEN 20

struct kobject {

const char * k_name;

char name[KOBJ_NAME_LEN];

struct kref kref;

struct list_head entry;

struct kobject * parent;

struct kset * kset;

struct kobj_type * ktype;

struct dentry * dentry;

wait_queue_head_t poll;

};

l entry

每个kset下面都可有一长串的kobject列表,此成员即用于此目的。

l dentry

由于每个kobject都将在sysfs文件系统中创建一个目录,这个值就是指向它的目录节点,因为sysfs是在内存中实现的,因而需要用一个dentry来表示,而不是一个inode

l k_name

这个成员可以单独指定一个名称,如果没有单独指定,它将指向此结构体的name成员。而且k_name不允许为空字符串。

kobject结构体使用kobject_init函数进行初始化:

/**

* kobject_init - initialize object.

* @kobj: object in question.

*/

void kobject_init(struct kobject * kobj)

{

if (!kobj)

return;

kref_init(&kobj->kref);

INIT_LIST_HEAD(&kobj->entry);

init_waitqueue_head(&kobj->poll);

kobj->kset = kset_get(kobj->kset);

}

通过此函数,引用计数设置为1

当要引用一个kobject对象时,通常使用kobject_get函数:

/**

* kobject_get - increment refcount for object.

* @kobj: object.

*/

struct kobject * kobject_get(struct kobject * kobj)

{

if (kobj)

kref_get(&kobj->kref);

return kobj;

}

/**

* kref_get - increment refcount for object.

* @kref: object.

*/

void kref_get(struct kref *kref)

{

WARN_ON(!atomic_read(&kref->refcount));

atomic_inc(&kref->refcount);

smp_mb__after_atomic_inc();

}

kobject_get函数将此kobject对象的引用加1后返回此对象。

1.1.3 kset

这个结构体用于表示某一类对象(用kobject表示)的集合,其定义为:

/**

* kset - a set of kobjects of a specific type, belonging

* to a specific subsystem.

*

* All kobjects of a kset should be embedded in an identical

* type. This type may have a descriptor, which the kset points

* to. This allows there to exist sets of objects of the same

* type in different subsystems.

*

* A subsystem does not have to be a list of only one type

* of object; multiple ksets can belong to one subsystem. All

* ksets of a subsystem share the subsystem's lock.

*

* Each kset can support specific event variables; it can

* supress the event generation or add subsystem specific

* variables carried with the event.

*/

struct kset_uevent_ops {

int (*filter)(struct kset *kset, struct kobject *kobj);

const char *(*name)(struct kset *kset, struct kobject *kobj);

int (*uevent)(struct kset *kset, struct kobject *kobj, char **envp,

int num_envp, char *buffer, int buffer_size);

};

struct kset {

struct kobj_type * ktype;

struct list_head list;

spinlock_t list_lock;

struct kobject kobj;

struct kset_uevent_ops * uevent_ops;

};

list这个成员可以很容易知道每个kset下面都将有许多的kobject。从kobj这个成员也可以猜测出内核是将kset也当成一个对象来看待的,呵呵。

通常使用kset_init函数进行此结构体的初始化:

/**

* kset_init - initialize a kset for use

* @k: kset

*/

void kset_init(struct kset * k)

{

kobject_init(&k->kobj);

INIT_LIST_HEAD(&k->list);

spin_lock_init(&k->list_lock);

}

注意在此并不改变uevent_ops成员的值,此值通常在定义kset的全局变量时初始化(可以初始化为NULL)。Ktype的值同样在全局变量定义时进行初始化,也可以设置为NULL

1.1.4 kobj_type

这个类型用以表示对某一类kobject的操作:

struct kobj_type {

void (*release)(struct kobject *);

struct sysfs_ops * sysfs_ops;

struct attribute ** default_attrs;

};

1.2 对象集的定义:decl_subsys

内核中使用了decl_subsys这个宏来定义一类对象集:

#define decl_subsys(_name,_type,_uevent_ops) \

struct kset _name##_subsys = { \

.kobj = { .name = __stringify(_name) }, \

.ktype = _type, \

.uevent_ops =_uevent_ops, \

}

比如在fs/namespace.c中就定义了这么一个对象集:

decl_subsys(fs, NULL, NULL);

这个对象集在mnt_init函数中进行注册:

err = subsystem_register(&fs_subsys);

在内核中搜索,可以发现有不少的decl_subsys

F:\embed\uClinux\uClinux-dist-2008R1.5-RC3\linux-2.6.x\block\genhd.c(611):decl_subsys(block, &ktype_block, &block_uevent_ops);

F:\embed\uClinux\uClinux-dist-2008R1.5-RC3\linux-2.6.x\drivers\base\bus.c(147):static decl_subsys(bus, &ktype_bus, NULL);

F:\embed\uClinux\uClinux-dist-2008R1.5-RC3\linux-2.6.x\drivers\base\class.c(75):static decl_subsys(class, &ktype_class, NULL);

F:\embed\uClinux\uClinux-dist-2008R1.5-RC3\linux-2.6.x\drivers\base\class.c(481):static decl_subsys(class_obj, &ktype_class_device, &class_uevent_ops);

F:\embed\uClinux\uClinux-dist-2008R1.5-RC3\linux-2.6.x\drivers\base\core.c(431):decl_subsys(devices, &ktype_device, &device_uevent_ops);

F:\embed\uClinux\uClinux-dist-2008R1.5-RC3\linux-2.6.x\drivers\base\firmware.c(19):static decl_subsys(firmware, NULL, NULL);

F:\embed\uClinux\uClinux-dist-2008R1.5-RC3\linux-2.6.x\drivers\base\sys.c(135):static decl_subsys(system, &ktype_sysdev_class, NULL);

F:\embed\uClinux\uClinux-dist-2008R1.5-RC3\linux-2.6.x\fs\namespace.c(44):decl_subsys(fs, NULL, NULL);

F:\embed\uClinux\uClinux-dist-2008R1.5-RC3\linux-2.6.x\kernel\ksysfs.c(66):decl_subsys(kernel, NULL, NULL);

F:\embed\uClinux\uClinux-dist-2008R1.5-RC3\linux-2.6.x\kernel\params.c(697):decl_subsys(module, &module_ktype, &module_uevent_ops);

这些kset的共同特点是它们都没有parent

1.3 注册对象集:subsystem_register

此函数用于注册一个kset,其实现在fs/kobject.c中:

int subsystem_register(struct kset *s)

{

return kset_register(s);

}

跟踪kset_register

/**

* kset_register - initialize and add a kset.

* @k: kset.

*/

int kset_register(struct kset * k)

{

if (!k)

return -EINVAL;

kset_init(k);

return kset_add(k);

}

挺简单的,先初始化kset结构体,再将它加入到内核中kset的链表中。

跟踪kset_add

/**

* kset_add - add a kset object to the hierarchy.

* @k: kset.

*/

int kset_add(struct kset * k)

{

return kobject_add(&k->kobj);

}

从这里可以明显看出kset本身的确也是一个kobject

跟踪kobject_add

/**

* kobject_add - add an object to the hierarchy.

* @kobj: object.

*/

int kobject_add(struct kobject * kobj)

{

return kobject_shadow_add(kobj, NULL);

}

跟踪kobject_shadow_add

/**

* kobject_shadow_add - add an object to the hierarchy.

* @kobj: object.

* @shadow_parent: sysfs directory to add to.

*/

int kobject_shadow_add(struct kobject * kobj, struct dentry *shadow_parent)

{

int error = 0;

struct kobject * parent;

if (!(kobj = kobject_get(kobj)))

return -ENOENT;

if (!kobj->k_name)

kobj->k_name = kobj->name;

if (!*kobj->k_name) {

pr_debug("kobject attempted to be registered with no name!\n");

WARN_ON(1);

kobject_put(kobj);

return -EINVAL;

}

parent = kobject_get(kobj->parent);

pr_debug("kobject %s: registering. parent: %s, set: %s\n",

kobject_name(kobj), parent ? kobject_name(parent) : "<NULL>",

kobj->kset ? kobj->kset->kobj.name : "<NULL>" );

if (kobj->kset) {

spin_lock(&kobj->kset->list_lock);

if (!parent)

parent = kobject_get(&kobj->kset->kobj);

list_add_tail(&kobj->entry,&kobj->kset->list);

spin_unlock(&kobj->kset->list_lock);

kobj->parent = parent;

}

error = create_dir(kobj, shadow_parent);

if (error) {

/* unlink does the kobject_put() for us */

unlink(kobj);

kobject_put(parent);

/* be noisy on error issues */

if (error == -EEXIST)

printk(KERN_ERR "kobject_add failed for %s with "

"-EEXIST, don't try to register things with "

"the same name in the same directory.\n",

kobject_name(kobj));

else

printk(KERN_ERR "kobject_add failed for %s (%d)\n",

kobject_name(kobj), error);

dump_stack();

}

return error;

}

此时shadow_parent参数为NULL

在此函数中,如果kobject有指定的kset,则将此object添加到kset的对象链表中,如果没有显式指定parent,则取kset做为它的parent

然后调用create_dir函数在sysfs文件系统中创建此kobject的入口。

1.4 kobject创建目录:create_dir

此函数的定义在lib/kobject.c

static int create_dir(struct kobject * kobj, struct dentry *shadow_parent)

{

int error = 0;

if (kobject_name(kobj)) {

error = sysfs_create_dir(kobj, shadow_parent);

if (!error) {

if ((error = populate_dir(kobj)))

sysfs_remove_dir(kobj);

}

}

return error;

}

两步走,先用sysfs_create_dir创建目录,如果没有发生错误,它将正确设置好kobject::dentry,使其指向正确的目录指针。如果此kobject有指定的parent<span s

你可能感兴趣的:(数据结构,C++,c,linux,C#)