一.数据结构设计
0.
需要被管理的实体实际上很杂,包括设备,驱动,总线,类型,块设备,电源等等...迫切需要统一管理。
1.
kobject代表每一个被管理实体,很显然的,这些实体可以带有一个或者多个属性。
2.
这些属性由attribute表示,由于被管理的实体不同,可能还会互相嵌套,因此很难给出一个明确的attribute的定义,因此使用了list_head的设计方式,将它仅仅作为一个锚点,真实的数据存在于它附近的内存区域,通过container_of宏来得到。(之所以可以这么做,得益于冯诺依曼机器的连续存储)
3.
另外,由于kobject也是一个锚点,并不携带真实数据,因此kobject和attribute之间也不便直接建立关系,而是通过kobj_type结构体解除耦合的。
4.
为了将被管理实体归类,设计了kset数据结构,管理一类kobject
5.
kset同时也是一个kobject,这就实现了一个组合模式。kobject的精化最终在这里体现。
二.用什么方式表现
1.
由于kobject将所有被管理实体组织成一个树型结构,因此任意可以表示树型结构的方式都可以采用。
2.
linux并不像windows导出很多操作接口(比如注册表,文件等),它基本只导出文件接口,也就是一个vfs接口,同时linux的文件系统组织是树型的,且实现了mount扩展机制,将不同类型的文件系统子树嫁接在根的任意子节点(需要是目录)上。
3.
很方便为kobject实现一个文件系统,然后mount到某一处。
4.
这个文件系统类型就是sysfs,一般处于/目录下的/sysfs目录中。
三.实现
1.
kobject的定义:
struct kobject {
const char *name; //名称
struct list_head entry; //
struct kobject *parent; //kobject组成链表,便于查找
struct kset *kset; //此kobj所属的kset
struct kobj_type *ktype; //kobj_type解耦了kobj和attr
struct sysfs_dirent *sd; //sysfs中的组织结构
struct kref kref; //引用计数
...
};
2.
kobj_type的定义:
struct kobj_type {
void (*release)(struct kobject *kobj);
struct sysfs_ops *sysfs_ops; //该kobj_type所属的kobject的所有attribute的总的store和show方法
struct attribute **default_attrs; //此type的属性们
};
3.
kset的定义:
struct kset {
struct list_head list; //属于此kset的kobj们
...
struct kobject kobj; //kset本身也是一个kobject,实现一个类别
struct kset_uevent_ops *uevent_ops; //实现向用户态的通知机制
};
4.
真实attribute的定义:
struct edac_pci_dev_attribute {
struct attribute attr; //所属的attribute结构锚点
void *value; //真实的,单独的attribute的值
ssize_t(*show) (void *, char *); //真实的,单独的attribute的show
ssize_t(*store) (void *, const char *, size_t);//真实的,单独的attribute的store
};
5.
每一个kobject在sysfs中都实现为一个目录,kobject是树型的,该树和sysfs中的目录树真切地对应。
6.
一个kobject的每一个attribute在sysfs中都实现为该kobject对应目录下的一个文件,所有的attribute统一由该kobject的kobj_type管理。
7.
sysfs文件系统中每一个文件代表它所属目录的kobject的一个属性,拥有读/写方法,即show/store。
8.
所有处于同一目录下的attribute的show/store统一由该目录所属kobject的kobj_type的show/store来分发,比如对于/sys/devices目录:
8.1.在注册一个顶层设备(比如总线等)时,均会将该device结构体的kobj的ktype初始化为device_ktype:
static struct kobj_type device_ktype = {
.release = device_release,
.sysfs_ops = &dev_sysfs_ops,
};
8.2.所有的8.1中注册的device的属性读写操作(show/store)全部通过以下的dev_sysfs_ops代理:
static struct sysfs_ops dev_sysfs_ops = {
.show = dev_attr_show,
.store = dev_attr_store,
};
static ssize_t dev_attr_show(struct kobject *kobj, struct attribute *attr, char *buf)
{
struct device_attribute *dev_attr = to_dev_attr(attr);
struct device *dev = to_dev(kobj);
ret = dev_attr->show(dev, dev_attr, buf);
}
8.3.对于每一个单独的属性,要单独定义,比如对于devt属性:
static struct device_attribute devt_attr =
__ATTR(dev, S_IRUGO, show_dev, NULL);
定义完之后,通过device_create_file加入sysfs文件系统:
device_create_file(dev, &devt_attr);
8.4.当dev_attr_show中调用dev_attr->show时,执行流被路由到show_dev函数:
static ssize_t show_dev(struct device *dev, struct device_attribute *attr, char *buf)
{
return print_dev_t(buf, dev->devt);
}
每一个kobject代表一个目录,其sd字段将kobject树转换成了sysfs文件系统的文件目录树。注意,sysfs使用dentry中的d_fsdata字段和kobject解除了耦合,所有的操作只有在接口层面上操作dentry和inode,进入后就会通过dentry的d_fsdata字段和inode的i_private字段转换为kobject机制的结构,比如sysfs_dirent结构。
四.和Windows管理方式的对比
1.
windows使用GUID来管理设备,驱动,总线,类型,块设备,电源等等...它本身就很统一。
2.
windows使用注册表来管理这些,例如HKEY_LOCAL_MACHINE/SYSTEM/ControlSet001/Control/Class键下面保存有各种类型的被管理实体,对应于linux的sysfs的根目录。
3.
GUID是个无结构的大数,通过复杂的算法生成,只求唯一性,GUID之间没有关联性,耦合性更低。kobject恰恰相反,它在本机范围内构建了一个树型的被管理实体结构。
4.
sysfs便于查找,而GUID某种意义上只能遍历,消耗很大,这就是注册表随着时间增加会拖慢系统速度的原因之一。
5.
GUID方式的管理也支持属性,并且节点也可以包含到其它节点的链接,这点和sysfs很相似。
6.
微软希望使用GUID来管理所有它能管理的实体,甚至包括office文档,然而这被证明不是一个好主意,虽然一个大数耦合性很低,内聚性很强,然而内聚性过强也会导致不能和外界通信。
7.
总之,GUID的方式没有做到恰到好处。
五.总结
1.
Linux使用kobject-一个组合模式的数据结构。
2.
Windows使用GUID-一个无耦合全内聚的数字。
3.
处处都存在设计模式。
3.1.面向对象的思想(OO)在kobject的设计中表现的很淋漓,具体就在kobj_type,虽然使用了type这个词,但实际上就是class,一个kobject的具体attitude就是一个kobj_type这个class的一个实例,由于kobject是表征凌乱不堪的实体的,因此kobject肯定区分了不同的类型,每一种类型的“操作attitude的方式(方法)”肯定相同,因此出现了kobj_type这个数据结构来解除分类的kobject与无类别的attitude之间的耦合。
3.2.锚点的设计方式其实在我们日常生活中也很普遍,比如身份证就代表某个人,人与人不同,然而身份证的格式是一样的,个人就是杂乱不堪的被管理实体,身份证就是kobject
分享到:
相关推荐
本文件分析了linux内核中设备模型kobject相关结构体。
kobject_init用来初始化kobject结构,kobject_add用来把kobj加入到... kobject_init_and_add和kobject_init这两个函数被调用后,kobj的引用计数会初始化为1, 所以在module_exit时要记得用kobject_put来释放引用计数。
linux kobject kset测试代码,以及根据kobject,kset写了符合linux设备驱动模型的ymj总线
linux 中 设备模型 中bus device driver kobject kset 集合
关于kset_create_and_add和kobject_init_and_add的流程图解释及关系总结。
kobject & kset实验 从/sys目录的构成可知整个sysfs文件系统盘根错节,此处补充一个向系统添加kobject & kset对象的实验,帮助理解该过程(但不会过分深入细节)
Linux设备模型kobject与kset之间的关系汇总
Linux 用户空间使用Netlink监听uevent,不是原理介绍,而是实战demo
解析kobject、kobj_type和kset.jpg
熟悉kobject设备模型 了解其结构
解析kobject、kobj_type和kset.drawio
4.3.2 sysfs、kobject和设备类73 4.3.3 热插拔和冷插拔76 4.3.4 微码下载76 4.3.5 模块自动加载77 4.4 内存屏障78 4.5 电源管理79 4.6 查看源代码79 第5章 字符设备驱动程序81 5.1 字符设备驱动...
kobject结构体1
kobject相关笔记 linux 2.6内核增加了一个新的特性统一设备模型device model。此模型提供了一个独立的机制专门来表示设备,并描述其在系统中的拓扑结构。
一个kobject结构如下图的kobject 类型部分,而一个kset结构如下图的kset 类型部分,一个kobject加入一个kset,主要是kobject结
kobject、kset和子系统 361 低层sysfs操作 368 热插拔事件的产生 372 总线、设备和驱动程序 374 类 384 各环节的整合 388 热插拔 394 处理固件 401 快速索引 403 第十五章 内存映射和DMA 408 Linux的内存...
kobject、kset和子系统 低层sysfs操作 热插拔事件的产生 总线、设备和驱动程序 类 各环节的整合 热插拔 处理固件 快速索引 第十五章 内存映射和DMA Linux的内存管理 mmap设备操作 执行直接I/O访问 直接...
linux 2.6 内核设备驱动模型精华描述,包括链表、hash链表、kobject等
Linux 设备模型详细分析,包含多个文档,对kobject、kset等进行了分析,并有实例分析。
Linux设备模型论kobj_type与kobject之间的关系总结