关于Linux设备模型kobject,kset,ktype

字体大小: 中小 标准 ->行高大小: 标准

一、sysfs文件系统下的每个目录对应于一个kobj,kset是kobj的封装,内嵌了一个kobj,其代表kset自身,ktype代表属性操作集,但由于通用性,因此把ktype单独剥离出来,kobj,kset,ktype成为了各个驱动模型最底层的关联元素,并由此形成了sys下的各种拓扑结构。

二、关于kobject

      首先看一下kobject的原型

            [cpp]

  1. struct kobject {       const char      *name;         //名字   
  2.     struct list_head    entry;         //连接到kset建立层次结构        struct kobject      *parent;       //指向父节点,面向对象的层次架构   
  3.     struct kset     *kset;               struct kobj_type    *ktype;        //属性文件   
  4.     struct sysfs_dirent *sd;       struct kref     kref;          //引用计数   
  5.     unsigned int state_initialized:1;      //初始化状态...        unsigned int state_in_sysfs:1;  
  6.     unsigned int state_add_uevent_sent:1;       unsigned int state_remove_uevent_sent:1;  
  7.     unsigned int uevent_suppress:1;   };  

   分析一下kobject的初始化过程

   初始化函数为

           [cpp]

  1. ---int kobject_init_and_add(struct kobject *kobj, struct kobj_type *ktype,  //参数为kobject和属性结构体                 struct kobject *parent, const char *fmt, ...)  
  2. {       va_list args;  
  3.     int retval;       kobject_init(kobj, ktype);     
  4.     va_start(args, fmt);       retval = kobject_add_varg(kobj, parent, fmt, args);  
  5.     va_end(args);       return retval;  
  6. }   ---void kobject_init(struct kobject *kobj, struct kobj_type *ktype)  
  7. {       char *err_str;  
  8.     if (!kobj) {                        //kobj为NULL错误退出            err_str = "invalid kobject pointer!";  
  9.         goto error;       }  
  10.     if (!ktype) {                       //ktype为NULL错误退出            err_str = "must have a ktype to be initialized properly!/n";  
  11.         goto error;       }  
  12.     if (kobj->state_initialized) {   //如果初始化状态为1报错            /* do not error out as sometimes we can recover */  
  13.         printk(KERN_ERR "kobject (%p): tried to init an initialized "                  "object, something is seriously wrong./n", kobj);  
  14.         dump_stack();       }  
  15.     kobject_init_internal(kobj);       //初始化kobj         kobj->ktype = ktype;            //关联obj和ktype   
  16.     return;   error:  
  17.     printk(KERN_ERR "kobject (%p): %s/n", kobj, err_str);       dump_stack();  
  18. }   -------static void kobject_init_internal(struct kobject *kobj)  
  19. {       if (!kobj)  
  20.         return;       kref_init(&kobj->kref);        //计数变成1   
  21.     INIT_LIST_HEAD(&kobj->entry);  //都指向自己,prev和next        kobj->state_in_sysfs = 0;  
  22.     kobj->state_add_uevent_sent = 0;       kobj->state_remove_uevent_sent = 0;  
  23.     kobj->state_initialized = 1;   }  
  24. -------static int kobject_add_varg(struct kobject *kobj, struct kobject *parent,                   const char *fmt, va_list vargs)  
  25. {       int retval;  
  26.     retval = kobject_set_name_vargs(kobj, fmt, vargs);  //设置名字,名字中不能有“/”        if (retval) {  
  27.         printk(KERN_ERR "kobject: can not set name properly!/n");           return retval;  
  28.     }       kobj->parent = parent;                 //设置parent,其父节点   
  29.     return kobject_add_internal(kobj);   }  
  30. ----static int kobject_add_internal(struct kobject *kobj)   {  
  31.     int error = 0;       struct kobject *parent;  
  32.     if (!kobj)           return -ENOENT;  
  33.     if (!kobj->name || !kobj->name[0]) {             //名字不能为空            WARN(1, "kobject: (%p): attempted to be registered with empty "  
  34.              "name!/n", kobj);           return -EINVAL;  
  35.     }       parent = kobject_get(kobj->parent);  //如果parent为真,则增加kobj->kref计数,也就是父节点的引用计数   
  36.     /* join kset if set, use it as parent if we do not already have one */       if (kobj->kset) {                     
  37.         if (!parent)               parent = kobject_get(&kobj->kset->kobj);  //如果kobj-parent父节点为NULL那么就用kobj->kset->kobj   
  38.                                                                             //  作其父节点,并增加其引用计数            kobj_kset_join(kobj);                         //把kobj的entry成员添加到kobj->kset>list的尾部,现在的层次就是   
  39.         kobj->parent = parent;                     //kobj->kset->list指向kobj->parent         }                                                     //    ->parent 指向kset->kobj                             
  40.     pr_debug("kobject: '%s' (%p): %s: parent: '%s', set: '%s'/n",            kobject_name(kobj), kobj, __func__,  
  41.          parent ? kobject_name(parent) : "<NULL>",            kobj->kset ? kobject_name(&kobj->kset->kobj) : "<NULL>");  
  42.     error = create_dir(kobj);   //利用kobj创建目录和属性文件,其中会判断,如果parent为NULL那么就在sysfs_root下创建        if (error) {  
  43.         kobj_kset_leave(kobj);           kobject_put(parent);  
  44.         kobj->parent = NULL;           /* be noisy on error issues */  
  45.         if (error == -EEXIST)               printk(KERN_ERR "%s failed for %s with "  
  46.                    "-EEXIST, don't try to register things with "                      "the same name in the same directory./n",  
  47.                    __func__, kobject_name(kobj));           else  
  48.             printk(KERN_ERR "%s failed for %s (%d)/n",                      __func__, kobject_name(kobj), error);  
  49.         dump_stack();       } else  
  50.         kobj->state_in_sysfs = 1;       return error;  
  51. }   ---static int create_dir(struct kobject *kobj)  
  52. {       int error = 0;  
  53.     if (kobject_name(kobj)) {           error = sysfs_create_dir(kobj);       //创建目录   
  54.         if (!error) {               error = populate_dir(kobj);   //创建属性文件   
  55.             if (error)                   sysfs_remove_dir(kobj);  
  56.         }       }  
  57.     return error;   }  

此文章由 http://www.ositren.com 收集整理 ,地址为: http://www.ositren.com/htmls/57978.html