linux驱动(八)驱动设备模型

http://blog.csdn.net/xiahouzuoxin/article/details/8943863html

http://blog.chinaunix.net/uid-25627207-id-3343854.htmljava

http://blog.csdn.net/phunxm/article/details/8994311linux

http://blog.csdn.net/new_abc/article/details/7558845算法

http://www.cnblogs.com/andtt/articles/2178905.html网络

http://blog.csdn.net/heli200482128/article/details/51828745数据结构

2.6内核增长了一个引人注目的新特性——统一设备模型(device model)。设备模型提供了一个独立的机制专门来表示设备,并描述其在系统中的拓扑结构,从而使得系统具备如下优势:架构

(1)代码重复最小化ide

(2)提供诸如引用计数这样的统一机制。函数

(3)能够列举系统中全部的设备,观察它们的状态,而且查看它们链接的总线。ui

(4)能够将系统中的所有设备结构以的形式完整、有效的展示出来——包括全部的总线和内部链接。

(5)能够将设备和其对应的驱动联系起来,反之亦然。

(6)能够将设备按照类型加以归类,好比分类为输入设备,而无需理解物理设备的拓扑结构。

(7)能够沿设备树的叶子向其根的方向依次遍历,以保证能以正确顺序关闭各设备的电源。

最后一点是实现设备模型的最初动机,若想在内核中实现智能的电源管理,就须要来创建表示系统中设备拓扑关系的树结构。当在树上端的设备关闭电源时,内核必须首先关闭该设备节点如下的(处于叶子上的)设备电源。好比内核须要先关闭一个USB鼠标,而后才可关闭USB控制器;一样内核也必须在关闭PCI总线前先关闭USB控制器。简而言之,若要准确而又高效的完成上述电源管理目标,内核无疑须要一颗设备树

(注:设备模型与电源管理相关联,貌似匪夷所思,可实际上,一个新观点或模型出现,在其背后都是需求的刺激。最近以来,节电一直是Intel、IBM等大公司孜孜追求的目标,虚拟化技术的本质其实就是节能。或者说,在能源日趋紧张的今日,节能是人类共同追求的目标)。

为何驱动模型有助于电源管理,再说两句:

系统中全部硬件设备由内核全权负责电源管理。例如,在以电池供电的计算机进入“待机”状态时,内核应马上强制每一个硬件设备(硬盘,显卡,声卡,网卡,总线控制器等等)处于低功率状态。所以,每一个可以响应“待机”状态的设备驱动程序必须包含一个回调函数,它可以使得硬件设备处于低功率状态。并且,硬件设备 必须按准确的顺序进入“待机”状态,不然一些设备可能会处于错误的电源状态。例如,内核必须首先将硬盘置于“待机”状态,而后才是它们的磁盘控制器,由于若按照相反的顺序执行,磁盘控制器就不能向硬盘发送命令。

Linux设备驱动模型(二)-文件系统之视图

虽然设备模型的初衷是为了方便电源管理而提供出的一种设备拓扑结构,可是,为了方便调试,设备模型的开发者决定将设备结构树导出为一个文件系统,这就是sysfs文件系统,它能够帮助用户以一个简单文件系统的方式来观察系统中各类设备的拓扑结构。这个举措很快被证实是很是明智的,首先sysfs代替了先前处于/proc下的设备相关文件;另外它为系统对象提供了一个颇有效的视图。实际上,sysfs起初被称为driverfs。最终sysfs使得咱们认识到一个全新的对象模型很是有利于系统。今天全部2.6内核的系统都拥有sysfs文件系统,并且几乎都毫无例外的将其挂载。

图一是挂载于/sys目录下的sysfs文件系统的局部视图。

> mount -t sysfs sysfs /sys

/sys

     |—block/

     |   |–fd0

     |   |–had

     |   |–dev

     |   |–device->../../devices/pci0000:00/0000:00:1f.1/ide0/0.0

     |    …

     |–bus/

     |–class/

     |–devices/

     |–firmware/

     |–power/

     |–module/

sysfs的根目录下包含了七个目录:block,bus,class,devices,firmware,module和power。

(1)block目录下的每一个子目录都对应着系统中的一个块设备。反过来,每一个目录下又都包含了该块设备的全部分区。

(2)bus目录提供了一个系统总线视图。

(3)class目录包含了以高层功能逻辑组织起来的系统设备视图。

(4)devices目录是系统中设备拓扑结构视图,它直接映射出了内核中设备结构体的组织层次。

(5)firmware目录包含了一些诸如ACPI,EDD,EFI等低层子系统的特殊树。

(6)power目录包含了系统范围的电源管理数据。

(7)module目录包含了内核模块。模块是一种向Linux内核添加设备驱动程序、文件系统及其余组件的有效方法。

其中最重要的目录是devices,该目录将设备模型导出到用户空间。目录结构就是系统中实际的设备拓扑。其它目录中的不少数据都是将devices目录下的数据加以转换加工而得。好比,/sys/class/net/目录是以注册网络接口这一高层概念来组织设备关系的,在这个目中可能会有目录eth0,它里面包含的devices文件其实就是一个指回到devices下实际设备目录的符号链接。

随便看看任何你可访问到的Linux系统,这种系统设备视图至关准确和漂亮,并且能够看到class中的高层概念与devices中的低层物理设备,以及bus中的实际驱动程序之间互相联络是很是普遍的。

Linux设备驱动模型(三)-追根之溯源

软件设计的根本是把现实世界的事物用计算机世界的模型表示出来,Linux设备模型的设计采用了面向对象(Object Oriented)的思想。

在前一讲中,提到sysfs文件系统,sysfs文件系统的目标就是要展示设备驱动模型组件之间的层次关系。在Linux中,sysfs文件系统被安装于/sys目录下,见上图一。那么,在这样的目录树中,哪些目录是驱动模型要关注的对象

bus-系统中用于链接设备的总线,在内核中对应的结构体为structbus_type { …  };

device-内核所识别的全部设备,依照链接它们的总线对其进行组织,对应的结构体为struct device {…  };

class-系统中设备的类型(声卡,网卡,显卡,输入设备等),同一类中包含的设备可能链接到不一样的总线,对应的结构体为struct class{…  };

为何不对Power进行单独描述?实际上,Power与device有关,它只是device中的一个字段

除此以外,立马闪如今咱们脑子里的对象还有:driver-在内核中注册的设备驱动程序,对应的结构体为struct device_driver{…  };

以上bus,device,class,driver是能够感觉到的对象,在内核中都用相应的结构体来描述。而实际上,按照面向对象的思想,咱们须要抽象出一个最基本的对象,这就是设备模型的核心对象kobject

kobject是Linux 2.6引入的新的设备管理机制,在内核中就是一个struct kobject结构体。有了这个数据结构,内核中全部设备在底层都具备统一的接口,kobject提供基本的对象管理,是构成Linux2.6设备模型的核心结构,它与sysfs文件系统紧密关联,每一个在内核中注册的kobject对象都对应于sysfs文件系统中的一个目录kobject是组成设备模型的基本结构。相似于C++中的基类,比如MFC中的CObject、Java中的Object和COM中的IUnKnown。kobject嵌入于更大的对象中,即所谓的容器,如上面提到的bus,class,devices,drivers都是典型的容器,它们是描述设备模型的组件

---------------------------------------------------------------------------------------------------------------------------------------------------

kobj:

Linux内核里,kobject是组成Linux设备模型的基础,一个kobject对应sysfs里的一个目录。从面向对象的角度来讲,kobject能够看做是全部设备对象的基类,由于C语言并无面向对象的语法,因此通常是把kobject内嵌到其余结构体里来实现相似的做用,这里的其余结构体能够看做是kobject的派生类。Kobject为Linux设备模型提供了不少有用的功能,好比引用计数,接口抽象,父子关系等等,因此,在内核中,没有用kobject直接定义的变量,kobject只是做为一个抽象的基类而存在。通常都是将kobject嵌入到另外一个结构,这个结构就能够看作是kobject的一个子类。而kobject的子类会比较关心kobject的属性和方法。

内核里的设备之间是以树状形式组织的,在这种组织架构里比较靠上层的节点能够看做是下层节点的父节点,反映到sysfs里就是上级目录和下级目录之间的关系,在内核里,正是kobject帮助咱们实现这种父子关系。在kobject的定义里,name表示的是kobject在sysfs中的名字;指针parent用来指向kobject的父对象;Kref你们应该比较熟悉了,kobject经过它来实现引用计数;Kset指针用来指向这个kobject所属的kset;对于ktype,若是只是望文生义的话,应该是用来描述kobject的类型信息。

-----------------------------------------------------------------------------------------------------------------------------------------------------------

kset:

有时候,某个设备的可能具备多个kobject的子类对象,或者某些设备具备相同的特性,为了便于管理,应该把这些对象统一放入一个容器中。这里要用到的容器就是kset。kset只是kobject的一个集合。对应到Linux文件系统中,一个kset就是/sys下的一个文件夹。

Kset自己也是一个kobject,因此它在sysfs里一样表现为一个目录,但它和kobject的不一样之处在于kset能够看做是一个容器,若是你把它类比为C++里的容器类如list也无不可。Kset之因此能做为容器来使用,其内部正是内嵌了一个双向链表结构struct list_head

 

kset 象 kobj_type 结构的扩展; 一个 kset 是嵌入到相同类型结构的 kobject 的集合。但 struct kobj_type 关注的是对象的类型,而struct kset 关心的是对象的聚合和集合,其主要功能是包容,可认为是kobjects 的顶层容器类。每一个 kset 在内部包含本身的 kobject, 并能够用多种处理kobject 的方法处理kset。 ksets 老是在 sysfs 中出现; 一旦设置了 kset 并把它添加到系统中, 将在 sysfs 中建立一个目录;kobjects 没必要在 sysfs 中表示, 但kset中的每个 kobject 成员都在sysfs中获得表述。

kobject创建的目录下只能添加文件,
kset创建的目录下添加目录,
kset是具备相同类型的kobject的集合。

-----------------------------------------------------------------------------------------------------------------------------------------------------------

kobj与kset的关系

咱们看一下sys目录下的文件:

每一个文件夹都对应一个kobject,/sys/目录下的文件夹是kset中包含的kobject,

sys目录下的全部文件夹都是一个层次的,每一个文件夹都是一个kset,每一个kset->object 都指向sys的kset以及kset->kobject;

在追踪到子目录中:

如class目录:

这里的每个文件夹也都是一个kset,这个文件夹是在一个层次上的;

每一个kset->object 都指向class的kset以及kset->kobject;

追到最底层的文件夹对应一个kobject,kobject中的文件就是kstyle中的attribute;

设备模型就是这么一层层创建起来的;

-----------------------------------------------------------------------------------------------------------------------------------------------------------