kobject到底是什么?
它是驱动模型的骨架,从程序的角度来说,也可以理解为基类。通过sysfs文件系统为整体系统提供一个层级视图。
Kobject对于内核的作用是什么?
- 为容器保持一个引用计数器
- 保持一个容器的链表或者合集
- 为用户模式提供容器属性视图
内核事件层:
提供一个基于object的内核到用户层的通知系统,本质上它是通过netlink来实现的。
相关数据结构
include/linux/kobject.h:
/* kernel object:对应sysfs文件系统中的一个目录:
* 这个结构体一般不会单独的存在,一般会嵌入到其它的结构体中使用。
*/
struct kobject {
const char *name; //显示的目录名字
struct list_head entry; //连接另外同属kset的kobject结构
struct kobject *parent; //父节点,用来实现层级视图
struct kset *kset; //指向kset合集
struct kobj_type *ktype; //提供kobject一族具有的普遍特性
struct kernfs_node *sd; /* sysfs directory entry */
/* 引用计数,在注册当前的kobject或者向当前kobject注册子kobject时会增加引用计数
* 添加属性时不会增加引用计数
*/
struct kref kref;
#ifdef CONFIG_DEBUG_KOBJECT_RELEASE
struct delayed_work release;
#endif
unsigned int state_initialized:1;
unsigned int state_in_sysfs:1; //kobject是否存在于sysfs中
unsigned int state_add_uevent_sent:1;
unsigned int state_remove_uevent_sent:1;
unsigned int uevent_suppress:1;
};
设备驱动模型的核心数据结构是一个名叫kobject的普通数据结构,它会固定关联到sysfs文件系统:每个kobject在fs文件系统中都有一个相应的目录。Kobjects结构体会嵌入到一个用于描述设备驱动模型的元件中。比如buses, devices, and drivers(注意:这些结构体中都包含有kobject)。
结构体成员说明:
/* 引用计数,在注册当前的kobject或者向当前kobject注册子kobject时会增加引用计数
添加属性时不会增加引用计数 */
struct kref kref;
struct kset {
struct list_head list; //组织相同类型的object的链表
spinlock_t list_lock;
struct kobject kobj; //代表当前kset的内核kobject对象
const struct kset_uevent_ops *uevent_ops; //核心功能:此kset的uevent操作
} __randomize_layout;
struct kset_uevent_ops {
int (* const filter)(struct kset *kset, struct kobject *kobj); //需要过滤的事件
const char *(* const name)(struct kset *kset, struct kobject *kobj);
/* kset发送用户空间的事件 */
int (* const uevent)(struct kset *kset, struct kobject *kobj,
struct kobj_uevent_env *env);
};
从上面结构的成员来看,kset主要有两个作用:1.通过链表来组织相同类型的kbojet.2.通过kset_uevent_ops类提供kset集相关的uevnet操作。也即:维护相同类型的kobject,主要是在热插拔的时候通过kset_uevent_ops向用户空间发送事件。从而实现设备的动态加载和移除。
struct kobj_type {
void (*release)(struct kobject *kobj); //kobject对象释放回调函数
/* 和sysfs文件系统关联,来实现相关的操作.
* 这个也是属性的读写操作必须要包含关联kobject的原因,
* 因为只有这里提供和sysfs文件操作.
*/
const struct sysfs_ops *sysfs_ops;
struct attribute **default_attrs; //默认的属性组
const struct kobj_ns_type_operations *(*child_ns_type)(struct kobject *kobj);
const void *(*namespace)(struct kobject *kobj);
};
struct sysfs_ops {
ssize_t (*show)(struct kobject *, struct attribute *, char *);
ssize_t (*store)(struct kobject *, struct attribute *, const char *, size_t);
};
从上面的数据结构可以看出kobject_type主要的几个功能:1.提供kobject对象释放函数。2.syfs文件系统的操作合集。3.体用默是的属性组。其中sys_ops提供show()和store()回调函数,作用跟它们的名字一样,起显示和保存的作用。
结构体之间的关系
kobject是整个文件系统的核心、基础,它类似于c++中的基类的作用。其中通过*parent的指针来构建了整个文件系统的视图。而在实际的使用中将它嵌入到其它的字符设备、平台设备等的结构,这样就将他们关联起来了。这种技巧在linux很多地方都有使用,比如container_of()。
kset实际上就是很多类型相同的kobject的合集。
kobj_type 对应不同的类型。
下面这个图很好的展示了它们的关系:
kobject相关操作函数
include/linux/kobject.h:
extern void kobject_init(struct kobject *kobj, struct kobj_type *ktype);
int kobject_add(struct kobject *kobj, struct kobject *parent, const char *fmt, ...);
int kobject_init_and_add(struct kobject *kobj, struct kobj_type *ktype, struct kobject *parent,
const char *fmt, ...);
void kobject_del(struct kobject *kobj);
kset相关的操作函数
#include <linux/kobject.h>
void kset_init(struct kset *k)
int kset_register(struct kset *k)
void kset_unregister(struct kset *k)
static ssize_t kobj_attr_show(struct kobject *kobj, struct attribute *attr, char *buf)
static ssize_t kobj_attr_store(struct kobject *kobj, struct attribute *attr, const char *buf, size_t count)
疑问
kobject_init_and_add()中添加的buf_type和sysfs_create_file()的添加属性有什么区别和关系?
通常来讲,由kobject相关的ktype所提供的默认属性是充足的。但是在一些特殊情况下会碰到特殊的kobject实例,它希望(甚至是必须)有自己的属性-也许是通用属性没包含那些需要的数据或者函数,为此,内核为能在默认之上,再添加新属性而提供了sysfs_create_file()接口。需要注意的是,kobject中ktype所对应的sysfs_ops操作将负责处理新属性。也就是是sysfs不会直接调用attribute提供的show()函数和store()函数,所以,ktype所对应的sysfs_ops操作需要实现处理新添加的attribute属性的功能。