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,
# struct kobject 这个结构出现的主要目的是为了 sysfs 树里面One of the main purposes of a struct kobject is to appear in the sysfs tree.
include/linux/kobject.h:63struct kobject {const char *name; /*name表示kobject对象的名字,对应sysfs下的一个目录*/struct list_head entry; /*entry是kobject中插入的head_list结构,*/struct kobject *parent;/*parent是指向当前kobject父对象的指针,体现在sys结构中就是包含当前kobject对象的目录对象,*/struct kset *kset;/*kset表示当前kobject对象所属的集合 , 必须在调用kobject_init()之前设置kset字段。*/struct kobj_type *ktype;/*ktype表示当前kobject的类型。*/struct kernfs_node *sd; /* sysfs directory entry */struct kref kref;/*是对kobject的引用计数,当引用计数为0时,就回调之前注册的release方法释放该对象。*/#ifdef CONFIG_DEBUG_KOBJECT_RELEASEstruct delayed_work release;#endifunsigned int state_initialized:1;/*初始化标志位,在对象初始化时被置位,表示对象是否已经被初始化。*/unsigned int state_in_sysfs:1;/*表示kobject对象在sysfs中的状态,在对应目录中被创建则置1,否则为0。*/unsigned int state_add_uevent_sent:1;/*是添加设备的uevent事件是否发送标志,添加设备时会向用户空间发送uevent事件,请求新增设备。-*/unsigned int state_remove_uevent_sent:1;/*是删除设备的uevent事件是否发送标志,删除设备时会向用户空间发送uevent事件,请求卸载设备*/unsigned int uevent_suppress:1;};
kobject 对应的API
int kobject_set_name(ko, char *, ...)char *kobject_name(ko)void kobject_init(ko)struct kobject *kobject_get(ko)void kobject_put(ko)void kobject_cleanup(ko)int kobject_add(ko)void kobject_del(ko)int kobject_register(ko)void kobject_unregister(ko)int kobject_rename(ko, char *new_name)void kobject_hotplug(const char *action, ko)char *kobject_get_path(struct kset *, ko, int)
初始化
static void kobject_init_internal(struct kobject *kobj)void kobject_init(struct kobject *kobj, struct kobj_type *ktype)
kobject_init
void kobject_init(struct kobject *kobj, struct kobj_type *ktype)kobject_init_internal(kobj);static void kobject_init_internal(struct kobject *kobj)kref_init(&kobj->kref);/*初始化对应的链表*/INIT_LIST_HEAD(&kobj->entry);/*前面我们提到 kref->refcount 会被置1, 就是在这里操作*/static inline void kref_init(struct kref *kref)atomic_set(&kref->refcount, 1);
这个函数主要的目的是,清空List链表,以及将 refcount 置1
注册
/*kobject_add_internal*/int kobject_add(struct kobject *kobj, struct kobject *parent,const char *fmt, ...)kobject_add_internal(kobj);static int kobject_add_internal(struct kobject *kobj)parent = kobject_get(kobj->parent);kobj_kset_join(kobj);/* add the kobject to its kset's list */static void kobj_kset_join(struct kobject *kobj)kset_get(kobj->kset);/*kobject 中的entry节点,插入到kset链表中*//*kset这个参数是什么时候配置得了? 这个一般是自己手动配置得*/list_add_tail(&kobj->entry, &kobj->kset->list);static inline struct kset *kset_get(struct kset *k)return k ? to_kset(kobject_get(&k->kobj)) : NULL;static inline struct kset *to_kset(struct kobject *kobj){return kobj ? container_of(kobj, struct kset, kobj) : NULL;}/*** kobject_get - increment refcount for object. 自增* @kobj: object.*/struct kobject *kobject_get(struct kobject *kobj)kref_get(&kobj->kref);
- kset的赋值
struct kset {struct list_head list; # 这一个链表spinlock_t list_lock; # 链表锁 有什么用?struct kobject kobj; #const struct kset_uevent_ops *uevent_ops;};
对应得API
void kset_init(ks)struct kset *to_kset(ko)struct kset *kset_get(ks)void kset_put(ks)int kset_add(ks)int kset_register(ks)void kset_unregister(ks)struct kobject *kset_find_obj(ks, char *)
