kobject

<img src="https://xiazemin.github.io/MyBlog/img/kobject.jpeg"/> <!-- more --> 1. kobject


kobject是组成设备模型的基本结构。类似于java中的object类,是所有用来描述设备模型的数据结构的基类,它嵌入于所有的描述设备模型的容器对象中,例如bus,devices,drivers等。这些容器通过kobject链接起来,形成一个树状结构,这个树状结构与/sys中是一一对应的。需要注意的是,并不是说每一个kobject对象都需要在sysfs中表示,但是每一个被注册到系统中的kset都会被添加到sysfs文件系统中,一个kset对象就对应一个/sys中的一个目录,kset中的每一个kobject成员,都对应sysfs中一个文件或者一个目录。



kobject对自身实现什么功能并不感兴趣,它存在的意义在于把高级的对象链接到设备模型上。因此内核代码很少去创建一个单独的kobject对象,相反,kobject用于控制对大型域相关对象的访问(通过container_of)。下图是kobject相关的类图:




  1. ktype
    Kobj type数据结构包含三个域:一个release方法用于释放kobject占用的资源;一个sysfs ops指针指向sysfs操作表和一个sysfs文件系统缺省属性列表。Sysfs操作表包括两个函数store()和show()。当用户态读取属性时,show()函数被调用,该函数编码指定属性值存入buffer中返回给用户态;而store()函数用于存储用户态传入的属性值。



3.kset



kset最重要的是建立上层(sub-system)和下层的(kobject)的关联性。kobject 也会利用它来分辨自已是属于那一個类型,然後在/sys 下建立正确的目录位置。而kset 的优先权比较高,kobject会利用自已的kset 找到自已所属的kset,并把ktype 指定成该kset下的ktype,除非沒有定义kset,才会用ktype來建立关系。Kobject通过kset组织成层次化的结构,kset是具有相同类型的kobject的集合,也可以说kset具有kobject所有的功能.



4.subsystem



如果说kset是管理kobject 的集合,那么subsystem 就是管理kset 的集合。它描述系统中某一类设备子系统,如block subsys表示所有的块设备,对应于sysfs文件系统中的block目录。类似的,devices subsys对应于sysfs中的devices目录,描述系统中所有的设备。一个具体总线可称之为subsystem.如I2C,SPI子系统等.它们是bus的子系统.



kset 本身嵌有一个kobj实体作为所以同类kobj的’父母亲’,同时还维护一个链表kset child list, 这个链表中所有的kobj的kset分别指向“父母亲”的kset.



kobject是隐藏在sysfs虚拟文件系统后的机制,对于sysfs中的每一个目录,内核中都会存在一个对应的kobject。每一个kobject都输出一个或者多个属性,它们在kobject的sysfs目录中表现为文件,其中的内容由内核生成。



kobject在sysfs中始终是一个目录,这个目录包含一个或者多个属性。



分配给kobject的名字,是sysfs中的目录名字。



sysfs的入口目录的位置对应于kobject的parent指针。调用kobject_add的时候,如果parent为NULL,它将被设置为嵌入到心得kobject的kset中的kobject,这样,sysfs 分层结构通常与kset创建的内部结构相匹配。如果parent和kset都是null,则会在最高层创建目录。



管理和操作kobject
当了解了kobject的内部基本细节之后,我们该关注kobject的外部接口了。多数情况下,驱动程序并不必直接管理kobject,因为kobject是被嵌入一些特殊的数据结构中,并由相关的设备驱动去幕后管理,当然,kobject并不是有意在隐藏自己,它可以出现在设备驱动代码中,或者可以在设备驱动子系统本身中使用它。



使用kobject的第一步是肯定是先生明并初始化,和其他数据结构一样的步骤,kobject通过kobjec_init函数进行初始化,该函数定义在<linux/kobject.h>中:下面看一下kobject_init函数原型:



void kobject_init(struct kobjec * kobj,struct kobj_type * ktype);
函数的第一个参数就是需要被初始化的kobject对象,值得注意的一点是,kobject在初始化之前,必须清空,这个工作在kobject所在上层数据结构初始化的时候完成,如果kobject没有被清空,那么调用memset()即可:



memset(kobj,0,sizeof(kobject));
在清零后就可以安全的初始化parent,kset字段了:



struct kobject kobj;
kobj = kmalloc(sizeof(
kobj),GFP_KERNEL);
if(!kobj)
return -ENOMEM;
memset(kobj,0,sizeof(*kobj));
kobj->kset = my_kset;
kobject_init(kobj,my_ktype);
其实上面这些步骤完全可以用kobject_create来替代,调用kobject_create函数会返回一个新建的kobject对象



struct kobject * kobject_create(void);
使用相当简单:



struct kobject * kobj;
kobj = kobject_create();
if(!kobj)
return -ENOMEM;
大多数情况下应该调用kobject_create函数去创建kobject;
kobject还有一个最重要的功能,那就是为我们提供一个统一的引用技术系统,kobject初始化的时候引用计数会被设置为1,只要对象的引用计数不是0,那么该对象就会一直保留在内存中。



我们接下来会带领大家去探讨一下sysfs和kobject到底有什么关系,前面也有简单的提到,现在我们深入的去了解一下。



sysfs是存在与内存中的一个虚拟文件系统,它为我们提供kobject对象层次结构的视图。帮助用户能以一个简单的文件系统的方式来观察系统中各种设备的拓扑结构,借助属性对象,kobject可以用导入文件的方式,将内核变量提供给用户读取或者写入。


Category linux