您的位置:首页 > 移动开发 > Objective-C

深入分析kobject与sysfs的关系

2016-09-29 11:27 447 查看
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相关的类图:



2. 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的子系统.



kobject,kset ,子系统之间的关系如下图所示



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可以用导入文件的方式,将内核变量提供给用户读取或者写入。我们以下图中的iio:device0这个kobject为例来说明一下:



这个iio:device0 kobject有很多属性,如下:



我们对仍和一个属性,比如in_accel_enable这个属性,使用下面命令:

cat in_accel_enable


会调用驱动程序的相应的show方法,去读取内核中某个变量的值,并显示出来:



使用

echo 1 > in_accel_enable


这个命令,会调用相应的store方法,向系统中内核变量写数据



虽然设备模型的初衷是为了方便电源管理而提出的一种设备拓扑结构,但是sysfs是颇为意外的收获,为了方便调试,设备模型的开发者决定将设备结构树导出为一个文件系统,这个举措很快被证明是非常明智的,首先sysfs代替了先前处于proc下的设备相关文件,另外它为系统对象提供了一个很有效的视图。实际上sysfs被成为driverfs,它比kobject出现的要早,最终sysfs使我们认识到了一个全新的对象模型非常有利于系统,于是就诞生了kobject。

sysfs的诀窍是吧kobject对象与目录项紧密的联系起来,这点是通过kobject中的dentry字段实现的,dentry结构体表示目录项,通过链接kobject到指定的目录项,实现将kobject映射到该目录项中。从此,把kobject导出形成文件系统就变得如同在内存中构建目录项一样简单。kobject其实已经形成了一棵树,这棵树就是我们心爱的对象模型体系。由于kobject被映射到目录项,同时对象层次结构也已经在内存中形成了一棵树。

sysfs下的目录最终要的就是devices目录,该目录将设备模型导出到用户空间,目录结构就是系统中实际的设备拓扑结构。

关于kobject和sysfs就分析到这。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: