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:63
struct 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_RELEASE
struct delayed_work release;
#endif
unsigned 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 *)