kobject结构

Linux内核中有大量的驱动,而这些驱动往往具有类似的结构,根据面向对象的思想,我们就可以将这些共同的部分提取为父类,这个父类就是kobject,也就是驱动编程中使用的.ko文件的由来,下面这张图是我根据内核源码的kobject绘制的简单的UML图,从中可以看出,kobject包含了大量的设备必须的信息,而三大类设备驱动都需要包含这个kobject结构,也就是”继承”自kobject。一个kobject对象就对应sys目录中的一个设备。 A struct kobject代表内核对象,也许是设备,例如,在sysfs 文件系统中显示为目录的对象。
一个 struct kobject 结构体必须被kobject_init初始化。这样做kref_init会将(struct kref).refcount设置为1,

  1. # struct kobject 这个结构出现的主要目的是为了 sysfs 树里面
  2. One of the main purposes of a struct kobject is to appear in the sysfs tree.
  1. include/linux/kobject.h:63
  2. struct kobject {
  3. const char *name; /*name表示kobject对象的名字,对应sysfs下的一个目录*/
  4. struct list_head entry; /*entry是kobject中插入的head_list结构,*/
  5. struct kobject *parent;/*parent是指向当前kobject父对象的指针,体现在sys结构中就是包含当前kobject对象的目录对象,*/
  6. struct kset *kset;/*kset表示当前kobject对象所属的集合 , 必须在调用kobject_init()之前设置kset字段。*/
  7. struct kobj_type *ktype;/*ktype表示当前kobject的类型。*/
  8. struct kernfs_node *sd; /* sysfs directory entry */
  9. struct kref kref;/*是对kobject的引用计数,当引用计数为0时,就回调之前注册的release方法释放该对象。*/
  10. #ifdef CONFIG_DEBUG_KOBJECT_RELEASE
  11. struct delayed_work release;
  12. #endif
  13. unsigned int state_initialized:1;/*初始化标志位,在对象初始化时被置位,表示对象是否已经被初始化。*/
  14. unsigned int state_in_sysfs:1;/*表示kobject对象在sysfs中的状态,在对应目录中被创建则置1,否则为0。*/
  15. unsigned int state_add_uevent_sent:1;/*是添加设备的uevent事件是否发送标志,添加设备时会向用户空间发送uevent事件,请求新增设备。
  16. -*/
  17. unsigned int state_remove_uevent_sent:1;/*是删除设备的uevent事件是否发送标志,删除设备时会向用户空间发送uevent事件,请求卸载设备*/
  18. unsigned int uevent_suppress:1;
  19. };

kobject 对应的API

  1. int kobject_set_name(ko, char *, ...)
  2. char *kobject_name(ko)
  3. void kobject_init(ko)
  4. struct kobject *kobject_get(ko)
  5. void kobject_put(ko)
  6. void kobject_cleanup(ko)
  7. int kobject_add(ko)
  8. void kobject_del(ko)
  9. int kobject_register(ko)
  10. void kobject_unregister(ko)
  11. int kobject_rename(ko, char *new_name)
  12. void kobject_hotplug(const char *action, ko)
  13. char *kobject_get_path(struct kset *, ko, int)

初始化

  1. static void kobject_init_internal(struct kobject *kobj)
  2. void kobject_init(struct kobject *kobj, struct kobj_type *ktype)

kobject_init

  1. void kobject_init(struct kobject *kobj, struct kobj_type *ktype)
  2. kobject_init_internal(kobj);
  3. static void kobject_init_internal(struct kobject *kobj)
  4. kref_init(&kobj->kref);
  5. /*初始化对应的链表*/
  6. INIT_LIST_HEAD(&kobj->entry);
  7. /*前面我们提到 kref->refcount 会被置1, 就是在这里操作*/
  8. static inline void kref_init(struct kref *kref)
  9. atomic_set(&kref->refcount, 1);

这个函数主要的目的是,清空List链表,以及将 refcount 置1

注册

  1. /*kobject_add_internal*/
  2. int kobject_add(struct kobject *kobj, struct kobject *parent,
  3. const char *fmt, ...)
  4. kobject_add_internal(kobj);
  5. static int kobject_add_internal(struct kobject *kobj)
  6. parent = kobject_get(kobj->parent);
  7. kobj_kset_join(kobj);
  8. /* add the kobject to its kset's list */
  9. static void kobj_kset_join(struct kobject *kobj)
  10. kset_get(kobj->kset);
  11. /*kobject 中的entry节点,插入到kset链表中*/
  12. /*kset这个参数是什么时候配置得了? 这个一般是自己手动配置得*/
  13. list_add_tail(&kobj->entry, &kobj->kset->list);
  14. static inline struct kset *kset_get(struct kset *k)
  15. return k ? to_kset(kobject_get(&k->kobj)) : NULL;
  16. static inline struct kset *to_kset(struct kobject *kobj)
  17. {
  18. return kobj ? container_of(kobj, struct kset, kobj) : NULL;
  19. }
  20. /**
  21. * kobject_get - increment refcount for object. 自增
  22. * @kobj: object.
  23. */
  24. struct kobject *kobject_get(struct kobject *kobj)
  25. kref_get(&kobj->kref);
  • kset的赋值
    • 所以我们使用kobject_add 的时候一定要设置 kset 的value
      1. static struct kset *map_kset;
      2. kobject_init(&entry->kobj, &map_ktype);
      3. entry->kobj.kset = map_kset;
      4. ret = kobject_add(&entry->kobj, NULL, "%d", nr);

      struct kset 结构体

      前面我i们提到使用 kobject_add 之前。必须得手动给 kset赋值,显然这个kset自己私有配置得东西。那个结构体有什么用了?
  1. struct kset {
  2. struct list_head list; # 这一个链表
  3. spinlock_t list_lock; # 链表锁 有什么用?
  4. struct kobject kobj; #
  5. const struct kset_uevent_ops *uevent_ops;
  6. };

对应得API

  1. void kset_init(ks)
  2. struct kset *to_kset(ko)
  3. struct kset *kset_get(ks)
  4. void kset_put(ks)
  5. int kset_add(ks)
  6. int kset_register(ks)
  7. void kset_unregister(ks)
  8. struct kobject *kset_find_obj(ks, char *)

参考资料

Sysfs and kobjects