日期:2014-05-16  浏览次数:20706 次

Linux设备模型分析之kobject(基于3.10.1内核)

作者:刘昊昱 

博客:http://blog.csdn.net/liuhaoyutz

内核版本:3.10.1

 
一、kobject结构定义
kobject是Linux设备模型的最底层数据结构,它代表一个内核对象。
kobject结构体定义在include/linux/kobject.h文件中:

 60struct kobject {
 61    const char      *name;
 62    struct list_head    entry;
 63    struct kobject      *parent;
 64    struct kset     *kset;
 65    struct kobj_type    *ktype;
 66    struct sysfs_dirent *sd;
 67    struct kref     kref;
 68    unsigned int state_initialized:1;
 69    unsigned int state_in_sysfs:1;
 70    unsigned int state_add_uevent_sent:1;
 71    unsigned int state_remove_uevent_sent:1;
 72    unsigned int uevent_suppress:1;
 73};


name是这个内核对象的名字,在sysfs文件系统中,name将以一个目录的形式出现。
entry用于将该内核对象链接进其所属的kset的内核对象链表。
parent代表该内核对象的父对象,用于构建内核对象的层次结构。
kset是该内核对象所属的“内核对象集合”。
ktype是该内核对象的sysfs文件系统相关的操作函数和属性。
sd表示该内核对象对应的sysfs目录项。
kref的核心数据是一个原子型变量,用于表示该内核对象的引用计数。
state_initialized表示该内核对象是否已经进行过了初始化,1表示已经初始化过了。
state_in_sysfs表示该内核对象是否已经在sysfs文件系统中建立一个入口点。
state_add_uevent_sent表示加入内核对象时是否发送uevent事件。
state_remove_uevent_sent表示删除内核对象时是否发送uevent事件。
uevent_suppress表示内核对象状态发生变化时,是否发送uevent事件。
 
二、kobject初始化分析
分析kobject,我们从kobject_init_and_add函数开始看,该函数完成对kobject的初始化,建立kobject的层次结构,并将kobject添加到sysfs文件系统中,该函数定义在lib/kobject.c文件中,其内容如下:
360/**
361 * kobject_init_and_add - initialize a kobject structure and add it to the kobject hierarchy
362 * @kobj: pointer to the kobject to initialize
363 * @ktype: pointer to the ktype for this kobject.
364 * @parent: pointer to the parent of this kobject.
365 * @fmt: the name of the kobject.
366 *
367 * This function combines the call to kobject_init() and
368 * kobject_add().  The same type of error handling after a call to
369 * kobject_add() and kobject lifetime rules are the same here.
370 */
371int kobject_init_and_add(struct kobject *kobj, struct kobj_type *ktype,
372             struct kobject *parent, const char *fmt, ...)
373{
374    va_list args;
375    int retval;
376
377    kobject_init(kobj, ktype);
378
379    va_start(args, fmt);
380    retval = kobject_add_varg(kobj, parent, fmt, args);
381    va_end(args);
382
383    return retval;
384}


从注释中可以看出,kobject_init_and_add函数可以分为两部分,一个是kobject_init函数,对kobject进行初始化,另一个是kobject_add_varg函数,将kobject添加到kobject层次结构中。
先来看kobject_init函数,其定义如下:
256/**
257 * kobject_init - initialize a kobject structure
258 * @kobj: pointer to the kobject to initialize
259 * @ktype: pointer to the ktype for this kobject.
260 *
261 * This function will properly initialize a kobject such that it can then
262 * be passed to the kobject_add() call.
263 *
264 * After this function is called, the kobject MUST be cleaned up by a call
265 * to kobject_put(), not by a call to kfree directly to ensure that all of
266 * the memory is cleaned up properly.
267 */
268void kobject_init(struct kobject *kobj, struct kobj_type *ktype)
269{
270    char *err_str;
271
272    if (!kobj) {
273        err_str = "invalid kobject pointer!";
274        goto error;
275    }
276    if (!ktype) {
277        err_str = "must have a ktype to be initialized properly!\n";
278        goto error;
279    }
280    if (kobj->state_initialized) {
281        /* do not error out as sometimes we can recover */
282        printk(KERN_ERR "kobject (%p): tried to init an initialized "
283               "object, something is seriously wrong.\n", kobj);
284        dump_stack();
285    }
286
287    kobject_init_internal(kobj);
288    kobj->ktype = ktype;
289    return;
290
291error:
292    printk(KERN_ERR "kobject (%p): %s\n&