歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux基礎 >> Linux教程 >> 關於Linux設備模型kobject,kset,ktype

關於Linux設備模型kobject,kset,ktype

日期:2017/2/28 15:58:19   编辑:Linux教程

一、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. }
Copyright © Linux教程網 All Rights Reserved