kobject、kset和ktype的关系
在Linux驱动中,kobject、kset和ktype是设备模型的重要组成部分,它们的关系如下:
kobject
kobject是最基本的基类,可理解为Linux设备模型中的“通用基础单元” ,类似面向对象编程中的基类。不过由于C语言没有继承特性,它通常被嵌入到其他结构体中,以实现类似继承的效果。比如字符设备驱动的 cdev 结构体就嵌入了 kobject 结构体。
每个kobject对应sysfs文件系统中的一个目录,包含了该目录的一些基本信息,如目录名( name )、父目录指针( parent )、所属的kset指针( kset )等。它具有以下作用:
- sysfs表述:为内核对象在sysfs中创建可见表述。
- 数据结构关联:将设备模型中复杂的数据结构聚合在一起。
- 热插拔事件处理:子系统将产生的热插拔事件通知用户空间。
- 对象引用计数:通过 kref 实现对对象的引用计数。
kset
kset是kobject的容器,它可以包含多个kobject ,可看作是一组相关kobject的集合。比如, /sys/bus/pci/drivers/ 路径下可能有多个表示不同驱动的kobject,它们可以被组织在一个kset中。
kset本身也内嵌了一个kobject,通过这个内嵌的kobject,kset可以与其他kset或kobject建立层次关系,从而构建出sysfs文件系统的层级结构。例如,在sysfs中,不同的总线、设备类等都可以用kset来组织相关的kobject,形成一个有层次的设备模型视图。
ktype
ktype用于描述kobject的类型,它定义了一组kobject所共有的属性和操作 。因为同类设备往往具有相同的属性,将这些属性提取出来存放在ktype中,便于统一管理。
例如,对于某种类型的设备驱动,它们可能都有一些共同的属性,如电源管理、热插拔属性等,这些属性的操作方法和默认值等就可以在ktype中定义。kobject通过 ktype 指针与对应的ktype关联,从而获取其所属类型的属性和操作方法。
三者关系总结
kobject是基础,kset用于组织相关的kobject形成层次结构,ktype则描述kobject的类型属性。它们相互协作,共同构建了Linux设备模型的基础架构,使得内核能够以一种统一、有序的方式管理各种设备和驱动,并通过sysfs文件系统向用户空间展示设备模型的层次结构和设备属性等信息。 可以形象地把kobject看作是一个个“个体”,kset是将这些“个体”按照一定规则(如功能、类别等)组织起来的“团体”,而ktype则像是给这些“个体”和“团体”贴上的“标签”,标明了它们的共性和特征。
在Linux内核中, kobject 、 kset 和 ktype 的结构体定义及关系如下:
kobject结构体
c
struct kobject {
const char *name;
struct list_head entry;
struct kobject *parent;
struct kset *kset;
struct kobj_type *ktype;
struct kernfs_node sd; / sysfs directory entry */
struct kref kref;
unsigned int state_initialized:1;
unsigned int state_in_sysfs:1;
unsigned int state_add_uevent_sent:1;
unsigned int state_remove_uevent_sent:1;
unsigned int uevent_suppress:1;
};
- name :表示kobject在sysfs中的名称。
- parent :指向父kobject的指针,用于构建层级关系。
- kset :指向所属kset的指针,通过这个指针将kobject和kset关联起来,表明该kobject属于哪个集合。
- ktype :指向所属ktype的指针,通过它获取kobject的类型信息,包括属性和操作等。
- kref :引用计数,用于对象的生命周期管理。
kset结构体
c
struct kset {
struct list_head list;
spinlock_t list_lock;
struct kobject kobj;
const struct kset_uevent_ops *uevent_ops;
};
- list :是一个链表头,用于将包含的kobject链接起来,这样就可以将多个相关的kobject组织在一个kset中。
- kobj :内嵌的kobject,这使得kset自身也可以作为一个kobject参与到sysfs的层级结构中。通过这个内嵌的kobject,kset可以和其他kset或kobject建立父子等关系,比如在sysfs文件系统中形成层级目录结构。
- uevent_ops :定义了一组热插拔事件相关的操作函数。
ktype结构体
c
struct kobj_type {
void (*release)(struct kobject *kobj);
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);
};
- release :当kobject的引用计数为0时,调用该函数释放资源。
- sysfs_ops :定义了一组与sysfs文件系统操作相关的函数,例如读写属性文件等操作。
- default_attrs :指向一组默认的属性,这些属性会被添加到属于该ktype的kobject上,用于描述kobject的特征和信息。
三者关系总结
- kobject与kset:kobject通过 kset 指针指向所属的kset,而kset通过 list 链表将多个kobject组织在一起。同时,kset本身因为内嵌了kobject,所以也能作为一个普通的kobject参与sysfs层级构建。
- kobject与ktype:kobject通过 ktype 指针与对应的ktype关联,ktype定义了kobject的释放函数、sysfs操作函数以及默认属性等,使得属于同一ktype的kobject具有相同的属性和操作行为。
- kset与ktype:虽然它们之间没有直接的指针关联,但通过kset中包含的kobject间接关联。kset中的kobject会通过 ktype 指针获取其类型信息,也就是说kset中包含的多个kobject可能共享相同的ktype定义的属性和操作等特征。
总之, kobject 、 kset 和 ktype 通过结构体中的指针和成员变量相互协作,共同构建了Linux设备模型的基本框架,用于管理内核对象以及在sysfs中展示设备模型的层次结构和属性信息。