目录
6、kobject、ktpye、kset的相互关系以及整个设备模型的理解
0、前言
在之前学习设备驱动的时候,即字符设备驱动的注册与注销这篇文章的时候,在cdev_alloc()和cdev_init()中均出现了kobject_init()这个函数,在当时并不清楚是什么东西,因为当时在乎的是把设备驱动这个框架给学会,在昨天看到文章的时候,又想起来还有这么一个东西没有去搞懂,于是稍微学习了一下,做一个笔记在此。
1、为什么要有设备模型
实现设备模型的最初动机。若想在内核中实现智能的电源管理,就需要来建立表示系统中设备拓扑关系的树结构。当在树上端的设备关闭电源时,内核必须首先关闭该设备节点以下(处于叶子上的)设备电源。比如内核需要先关闭一个 USB 鼠标,然后才可以关闭 USB 控制器;同样内核也必须在关闭 PCI 总线前先关闭 USB 控制器。简而言之,若要准确又高效地完成上述电源管理目标,内核无疑需要一颗设备树。
2、设备驱动模型的优点
1、代码重复最小化
2、提供诸如引用计数这样的统一机制。
3、可以列举系统中所有的设备,观察它们的状态,并且查看它们连接的总线。
4、可以将系统中的全部设备结构以树的形式完整、有效地展现出来,包括所有的总线和内部连接
5、可以将设备和其对应的驱动联系起来,反之亦然。
6、可以将设备按照类型加以归类,如分类为输入设备,而无需理解物理设备的拓扑结构。
7、可以沿设备树的叶子向其根的方向依次遍历,以保证能以正确的顺序关闭各设备的电源。
3、 kobject
3.1 kobject结构体
struct kobject {
const char *name;
struct list_head entry;
struct kobject *parent;
struct kset *kset;
struct kobj_type *ktype;
struct kernfs_node *sd;
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;
};
3.2 kobject结构体各参数解析
@name:该指针指向此kobject的名称,对应 sysfs 的目录名。
@entry:用于将 kobj 挂在 kset->list 中。
@parent:指向 kobject 的父对象,这样kobject就会在内核中构造一个对象层次结构,将多 个对象间的关系表现出来。在sysfs中表现为父子目录的结构。
@kset:表示该 kobj 所属的 kset。
@ktype:表示该 kobj 对应的 kobj_type。
@sd:该结构体在sysfs中表示这个kobject。从sysfs文件系统内部看,这个结构体是表示kobject的一个inode结构体。
@kref:引用计数对象,支撑 kobj 的引用计数功能。
3.3 kobject结构体的使用位置
kobject通常是嵌入到其他结构中的,单独意义并不大,一些更为重要的结构体如struct cdev中才真正需要用到kobjcet结构。当kobjcet被嵌入到其他结构中,该结构便拥有了kobject提供的标准功能,嵌入kobject的结构体可以成为对象层次架构中的一部份。比如cdev结构体就可以通过其父指针cdev->kobj.parent和链表cdev->kobj.entry插入到对象层次结构中。例如:
struct cdev {
struct kobject kobj;
struct module *owner;
const struct file_operations *ops;
struct list_head list;
dev_t dev;
unsigned int count;
};
4、ktype
4.1 ktpte结构体原型
struct kobj_type {
void (*release)(struct kobject *kobj);
const struct sysfs_ops *sysfs_ops;
struct attribute **default_attrs;
};
4.2 ktype结构体各参数解析
@release:该函数指针指向一个析构函数,析构函数在kobject引用计数减至零时调用
@sysfs_ops:该种类型的kobject的sysfs文件系统接口(读属性接口show及写属性接口store)。
@default_attrs:该种类型的kobject的atrribute数组(所谓attribute,就是sysfs文件系统中的一个文件)。将会在kobject添加到内核时,一并注册到sysfs中。这些数组定义了该kobject相关的默认属性。
5、kset(特殊的kobject)
5.1 kset结构体原型
struct kset {
struct list_head list;
spinlock_t list_lock;
struct kobject kobj;
const struct kset_uevent_ops *uevent_ops;
};
5.2 kset结构体各参数解析
@list:连接该kset下所有的kobject的链表。
@list_lock:避免操作链表时产生竞态的自旋锁。
@kobj:该kset自己的kobject(kset是一个特殊的kobject,也会在sysfs中以目录的形式体现)。
@uevent_ops:该kset的uevent操作函数集,当kset中的某些kobject对象状态发生变化需要通知用户空间时,调用其中对应的函数来完成。当任何kobject需要上报uevent时,都要调用它所从属的kset的uevent_ops,添加环境变量,或者过滤event(kset可以决定哪些event可以上报)。因此,如果一个kobject不属于任何kset时,是不允许发送uevent的。是用于处理集合中object对象的热插拔操作的,提供了与用户空间热插拔信息进行通信的机制。
6、kobject、ktpye、kset的相互关系以及整个设备模型的理解
1、kobject的核心功能是:保持一个引用计数,当该计数减为0时,自动释放kobject所占用的空间(由ktype中的回调函数release负责释放所有kobject使用的内存以及其他相关清理工作)。这就决定了kobject必须是动态分配的,因为只有这样才能动态释放。
2、kobject通过parent指针,可以将所有kobject以层次结构的形式组合起来。
3、和sysfs虚拟文件系统配合,将每一个kobject及其特性,以文件的形式显示到用户空间。sysfs看到的是kobject,而真正的文件操作的主体,是内嵌kobject的上层数据结构。4、kobject是基本数据类型,每个kobject都会在"/sys/“文件系统中以目录的形式出现。
5、ktype代表kobject的属性操作集合。由于通用性,多个kobject可能共用同一个属性操作集,因此把ktype独立出来了。ktpye定义了一些kobject相关的默认特性:析构行为、sysfs行为(sysfs的操作表)以及别的一些默认属性。
6、kset是一个特殊的kobject(因此它也会在"/sys/“文件系统中以目录的形式出现),它用来集合相似的kobject(这些kobject可以是相同属性的,也可以不同属性的)。
7、kobject大数多数的使用场景,是内嵌在大型的据结构中(如kset、device_driver、cdev等),因此这些大型的数据结构,也必须是动态分配、动态释放的。

本文介绍了Linux内核中的设备模型,重点讲解了kobject、ktype和kset的作用,包括它们在设备驱动中的角色、结构体解析和相互关系。kobject提供引用计数和对象层次结构,ktype定义了对象的属性操作,kset则用于组织相似的kobject并支持uevent操作。
1255

被折叠的 条评论
为什么被折叠?



