linux 驱动模型的数据结构

来源:互联网 发布:如何解决网络丢包问题 编辑:程序博客网 时间:2024/05/18 03:36

sysfs文件系统
sysfs文件系统是一种特殊的文件系统,在系统启动时,被安装在/sys目录,目标主要是展现设备驱动程序模型组件间的层次关系。所包含的目录如下:
block
 块设备,它们独立于所连接的总线
devices
 所有被内核识别的硬件设备,都挂在它们的总线上。
bus
 系统中大部分设备,依靠总线进行连接
drivers
 注册过的设备驱动程序
class
 系统中设备的类型
power
 设备电源状态文件
firmware
 固件文件
sysfs文件系统所表示设备驱动程序模型组件之间的关系,就像目录和文件之间符号链接的关系一样。比如,文件/sys/block/sda/device可以是一个符号链接,指向在/sys/devices/pci0000:00中嵌入的一个子目录。
在sysfs中普通文件的主要作用是表示驱动程序和设备的属性。例如,位于目录/sys/block/had下的dev文件含有第一个IDE设备的主,次设备号。
在sysfs中有几个核心的对象,分别是kobject,kset,subsystem,在现在内核系统中,subsystem已经和kset区别不大了。下面分别介绍这几个对象。

kobject对象

设备驱动程序模型的核心数据结构,它与sysfs文件系统是绑定在一起呢,为什么这么说,因为在sysfs文件下面,有好多文件夹,每个文件夹都会对应一个kobject对象。kobject不是孤立的存在,它会嵌入到kset容器中。容器的例子有bus,device等。
kobject的数据结构如下

ktype字段所指是同一类型的kobject,kobj_type数据结构包括三个字段;release方法,指向sysfs操作表的sysfs_ops指针以及sysfs文件系统的缺省属性链表。
kref字段是一个k_ref类型的结构,包括一个refcount字段,用于对kobject的引用计数,也可以做为kobject容器的引用计数。kobject_get()函数和kobject_put()函数用于增加和减少引用计数。当计数器的值为0时,就可以释放kobject使用的资源。同时执行kobject的类型中kobj_type对象的release访求。

kset对象
kset对象可以将kobjects组织成一棵层次树。kset是同类型kobject结构的一个集合体。相关的kobject包含在同类型的容器中。kset数据结构如下

 

list字段表示包含在kset中的kobject结构的双向循环链表的首部。ktype字段是指向kset中的kobj_type描述符的指针。kobj字段是嵌入在kset数据结构中的kobject;,而位于kset中的kobject,是单独kobject的父指针所指向的。
kset_get()函数和kset_put()分别用于kset引用计数器的增加和减少。

subsystem对象
它是kset的集合。一个subsystem可以包括不同类型的kset。其包含的数据结构如下
kset
 内嵌kset结构,用于存放subsystem中的kset.
rwsem
 读写信号量,保护递归地包含于subsystem中的所有kset和kobject.
subsystem数据结构也可以嵌入到一个更大的容器中。也有像前两个对象的一样的函数,用于增加和减少引用计数。

三个对象的注册和移除
kobject_register()函数,用于初始化kobject,并将其相应的目录增加到sysfs文件系统中。kobject_unregister()函数,用于将kobject的目录从sysfs文件系统中移走。
kset_register()和kset_unregister,及subsystem_register()和subsystem_unregister()函数是在kobject的函数上封装的。

设备驱动程序模型组件

设备驱动程序模型建立在下面的几个数据结构之上的,分别是总线、设备、设备驱动。

设备
内核中,每个设备由一个device对象来描述。其实结构如下

device对象全部在设备子系统里面,目录为/sys/devices.设备是层次关系组织的,一个设备是某个“孩子”的“父亲”,其条件是子设备离开了父设备了,无法正常工作。
每个设备驱动程序是都保持一个device对象的链表,其中链接了所有可被管理的设备;
device对象的driver_list字段存放指向相邻对象的指针,driver字段指向设备驱动程序的描述符。对于总线来说,都有一个链表存放连接到该类型总线上的所有设备;device对象的bus_list字段存放指向相邻对象的指针,而bus字段指向总线类型描述符。
引用计数器用来记录device对象的使用情况,可能调用get_device()和put_device()函数分别增加和减少该计数器的值。它包含在kobject类型的kobj结构中。
device_register()函数用来往驱动模型中插入一个新的设备对象,并自动在/sys/devices目录下创建一个新的目录。

驱动程序
设备驱动程序模型中的每个驱动程序都可用device_driver对象描述。其字段如下:

device对象全部在设备子系统里面,目录为/sys/devices.设备是层次关系组织的,一个设备是某个“孩子”的“父亲”,其条件是子设备离开了父设备了,无法正常工作。
每个设备驱动程序是都保持一个device对象的链表,其中链接了所有可被管理的设备;
device对象的driver_list字段存放指向相邻对象的指针,driver字段指向设备驱动程序的描述符。对于总线来说,都有一个链表存放连接到该类型总线上的所有设备;device对象的bus_list字段存放指向相邻对象的指针,而bus字段指向总线类型描述符。
引用计数器用来记录device对象的使用情况,可能调用get_device()和put_device()函数分别增加和减少该计数器的值。它包含在kobject类型的kobj结构中。
device_register()函数用来往驱动模型中插入一个新的设备对象,并自动在/sys/devices目录下创建一个新的目录。

驱动程序
设备驱动程序模型中的每个驱动程序都可用device_driver对象描述。其字段如下:

 

每个bus_type类型的对象都包含一个内嵌的子系统;存放在bus_subsys变量中的子系统把嵌入在bus_type对象中的所有子系统都集合在一起。其目录位于/sys/bus下

driver中的device_driver,描述与总线类型相关的所有设备驱动程序,名为devices包含的device描述符,描述了给定总线类型上连接的所有设备。总线下的设备都是devices下面的符号链接。

当内核检查一个给定的设备是否可以由给定的驱动程序处理时,会使用总线的match方法。