感谢支持
我们一直在努力

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

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


二、关于kobject


      首先看一下kobject的原型


           

[cpp]


  1. struct kobject {  

  2.     const char      *name;         //名字   

  3.     struct list_head    entry;         //连接到kset建立层次结构   

  4.     struct kobject      *parent;       //指向父节点,面向对象的层次架构   

  5.     struct kset     *kset;          

  6.     struct kobj_type    *ktype;        //属性文件   

  7.     struct sysfs_dirent *sd;  

  8.     struct kref     kref;          //引用计数   

  9.     unsigned int state_initialized:1;      //初始化状态…   

  10.     unsigned int state_in_sysfs:1;  

  11.     unsigned int state_add_uevent_sent:1;  

  12.     unsigned int state_remove_uevent_sent:1;  

  13.     unsigned int uevent_suppress:1;  

  14. };  


   分析一下kobject的初始化过程


   初始化函数为


          

[cpp]


  1. int kobject_init_and_add(struct kobject *kobj, struct kobj_type *ktype,  //参数为kobject和属性结构体   

  2.              struct kobject *parent, const char *fmt, …)  

  3. {  

  4.     va_list args;  

  5.     int retval;  

  6.     kobject_init(kobj, ktype);     

  7.     va_start(args, fmt);  

  8.     retval = kobject_add_varg(kobj, parent, fmt, args);  

  9.     va_end(args);  

  10.     return retval;  

  11. }  

  12. void kobject_init(struct kobject *kobj, struct kobj_type *ktype)  

  13. {  

  14.     char *err_str;  

  15.     if (!kobj) {                        //kobj为NULL错误退出   

  16.         err_str = “invalid kobject pointer!”;  

  17.         goto error;  

  18.     }  

  19.     if (!ktype) {                       //ktype为NULL错误退出   

  20.         err_str = “must have a ktype to be initialized properly!/n”;  

  21.         goto error;  

  22.     }  

  23.     if (kobj->state_initialized) {   //如果初始化状态为1报错   

  24.         /* do not error out as sometimes we can recover */  

  25.         printk(KERN_ERR “kobject (%p): tried to init an initialized “  

  26.                “object, something is seriously wrong./n”, kobj);  

  27.         dump_stack();  

  28.     }  

  29.     kobject_init_internal(kobj);       //初始化kobj    

  30.     kobj->ktype = ktype;            //关联obj和ktype   

  31.     return;  

  32. error:  

  33.     printk(KERN_ERR “kobject (%p): %s/n”, kobj, err_str);  

  34.     dump_stack();  

  35. }  

  36. ——-static void kobject_init_internal(struct kobject *kobj)  

  37. {  

  38.     if (!kobj)  

  39.         return;  

  40.     kref_init(&kobj->kref);        //计数变成1   

  41.     INIT_LIST_HEAD(&kobj->entry);  //都指向自己,prev和next   

  42.     kobj->state_in_sysfs = 0;  

  43.     kobj->state_add_uevent_sent = 0;  

  44.     kobj->state_remove_uevent_sent = 0;  

  45.     kobj->state_initialized = 1;  

  46. }  

  47. ——-static int kobject_add_varg(struct kobject *kobj, struct kobject *parent,  

  48.                 const char *fmt, va_list vargs)  

  49. {  

  50.     int retval;  

  51.     retval = kobject_set_name_vargs(kobj, fmt, vargs);  //设置名字,名字中不能有“/”   

  52.     if (retval) {  

  53.         printk(KERN_ERR “kobject: can not set name properly!/n”);  

  54.         return retval;  

  55.     }  

  56.     kobj->parent = parent;                 //设置parent,其父节点   

  57.     return kobject_add_internal(kobj);  

  58. }  

  59. —-static int kobject_add_internal(struct kobject *kobj)  

  60. {  

  61.     int error = 0;  

  62.     struct kobject *parent;  

  63.     if (!kobj)  

  64.         return -ENOENT;  

  65.     if (!kobj->name || !kobj->name[0]) {             //名字不能为空   

  66.         WARN(1, “kobject: (%p): attempted to be registered with empty “  

  67.              “name!/n”, kobj);  

  68.         return -EINVAL;  

  69.     }  

  70.     parent = kobject_get(kobj->parent);  //如果parent为真,则增加kobj->kref计数,也就是父节点的引用计数   

  71.     /* join kset if set, use it as parent if we do not already have one */  

  72.     if (kobj->kset) {                     

  73.         if (!parent)  

  74.             parent = kobject_get(&kobj->kset->kobj);  //如果kobj-parent父节点为NULL那么就用kobj->kset->kobj   

  75.                                                                             //  作其父节点,并增加其引用计数   

  76.         kobj_kset_join(kobj);                         //把kobj的entry成员添加到kobj->kset>list的尾部,现在的层次就是   

  77.         kobj->parent = parent;                     //kobj->kset->list指向kobj->parent    

  78.     }                                                     //    ->parent 指向kset->kobj                             

  79.     pr_debug(“kobject: ‘%s’ (%p): %s: parent: ‘%s’, set: ‘%s’/n”,  

  80.          kobject_name(kobj), kobj, __func__,  

  81.          parent ? kobject_name(parent) : “<NULL>”,  

  82.          kobj->kset ? kobject_name(&kobj->kset->kobj) : “<NULL>”);  

  83.     error = create_dir(kobj);   //利用kobj创建目录和属性文件,其中会判断,如果parent为NULL那么就在sysfs_root下创建   

  84.     if (error) {  

  85.         kobj_kset_leave(kobj);  

  86.         kobject_put(parent);  

  87.         kobj->parent = NULL;  

  88.         /* be noisy on error issues */  

  89.         if (error == -EEXIST)  

  90.             printk(KERN_ERR “%s failed for %s with “  

  91.                    “-EEXIST, don’t try to register things with “  

  92.                    “the same name in the same directory./n”,  

  93.                    __func__, kobject_name(kobj));  

  94.         else  

  95.             printk(KERN_ERR “%s failed for %s (%d)/n”,  

  96.                    __func__, kobject_name(kobj), error);  

  97.         dump_stack();  

  98.     } else  

  99.         kobj->state_in_sysfs = 1;  

  100.     return error;  

  101. }  

  102. static int create_dir(struct kobject *kobj)  

  103. {  

  104.     int error = 0;  

  105.     if (kobject_name(kobj)) {  

  106.         error = sysfs_create_dir(kobj);       //创建目录   

  107.         if (!error) {  

  108.             error = populate_dir(kobj);   //创建属性文件   

  109.             if (error)  

  110.                 sysfs_remove_dir(kobj);  

  111.         }  

  112.     }  

  113.     return error;  

  114. }  

三、关于 kset


      首先看一下kset的原型


         

[cpp]


  1. struct kset {  

  2.     struct list_head list;  //连接着他下面的kobj成员,与kobj-entry关联   

  3.     spinlock_t list_lock;  

  4.     struct kobject kobj;    //代表kset自己   

  5.     const struct kset_uevent_ops *uevent_ops;  

  6. };  


       再来看一下kset的初始化操作,kset表现为更高级一点的kobj,其初始化操作仍然是围绕其内部的kobj展开的。


 


         

[cpp]


  1. struct kset *kset_create_and_add(const char *name,  

  2.                  const struct kset_uevent_ops *uevent_ops,  

  3.                  struct kobject *parent_kobj)  

  4. {  

  5.     struct kset *kset;  

  6.     int error;  

  7.     kset = kset_create(name, uevent_ops, parent_kobj);  //创建kset,关联操作函数和其父节点   

  8.     if (!kset)  

  9.         return NULL;  

  10.     error = kset_register(kset);  

  11.     if (error) {  

  12.         kfree(kset);  

  13.         return NULL;  

  14.     }  

  15.     return kset;  

  16. }  

  17. static struct kset *kset_create(const char *name,  

  18.                 const struct kset_uevent_ops *uevent_ops,  

  19.                 struct kobject *parent_kobj)  

  20. {  

  21.     struct kset *kset;  

  22.     int retval;  

  23.     kset = kzalloc(sizeof(*kset), GFP_KERNEL);  //申请结构体内存   

  24.     if (!kset)  

  25.         return NULL;  

  26.     retval = kobject_set_name(&kset->kobj, name);  //设置名字   

  27.     if (retval) {  

  28.         kfree(kset);  

  29.         return NULL;  

  30.     }  

  31.     kset->uevent_ops = uevent_ops;               //关联操作函数   

  32.     kset->kobj.parent = parent_kobj;             //关联父节点   

  33.     /* 

  34.      * The kobject of this kset will have a type of kset_ktype and belong to 

  35.      * no kset itself.  That way we can properly free it when it is 

  36.      * finished being used. 

  37.      */  

  38.     kset->kobj.ktype = &kset_ktype;            //关联属性文件   

  39.     kset->kobj.kset = NULL;                      

  40.     return kset;  

  41. }  

  42. —-int kset_register(struct kset *k)  

  43. {  

  44.     int err;  

  45.     if (!k)  

  46.         return -EINVAL;  

  47.     kset_init(k);  

  48.     err = kobject_add_internal(&k->kobj);     //调用kobj操作函数       

  49.     if (err)  

  50.         return err;  

  51.     kobject_uevent(&k->kobj, KOBJ_ADD);  

  52.     return 0;  

  53. }  

  54. —-void kset_init(struct kset *k)  

  55. {  

  56.     kobject_init_internal(&k->kobj);          //调用kobj操作函数   

  57.     INIT_LIST_HEAD(&k->list);  

  58.     spin_lock_init(&k->list_lock);  

  59. }  


四、上面给出了kobj,kset的初始化过程,以及相互产生关联的关键点,下面给出整体的一个流程图:


         kset,kobj流程图

赞(0) 打赏
转载请注明出处:服务器评测 » 关于Linux设备模型kobject,kset,ktype
分享到: 更多 (0)

听说打赏我的人,都进福布斯排行榜啦!

支付宝扫一扫打赏

微信扫一扫打赏