WDM驱动开发之路写在前面:在专栏的前几期中,我们一起初步学习了vxd的开发技术。
Vxd技术是很深奥的,不是一篇两篇文章能讲清楚,但你已经入了门,剩下的就要看你的修行了。
多看书,多泡论坛(当然是上咱们的驱动开发网论坛了:->),多写程序…我的手不够用了。
功到自然成嘛。
不过话又说回来,vxd只是权宜之计,WDM才符合当今的潮流(程序员都是时髦人士,君不见先是VB、VC然后是asp、JSP、PHP,数也数不过来呀),Win9x寿终正寝时也就是vxd的末日,你不想随它而去吧(开个玩笑),那就随我来。
按笔者的想法,这篇文章写成连载形式,一次讲一个主题,并且必要时带着例子,让大伙step by step地把WDM驱动弄个透底,不想让大家觉得稀里糊涂,也不想让大家觉得白买杂志了。
今天我们一起讨论第一部分,了解篇。
(一)了解篇WDM模型(Windows Driver Model)是微软公司为当前主流操作系统Windows98和Windows 2000的驱动程序设计的一种构架。
它和传统的win3.x和win95使用的vxd的驱动是完全不同的体系结构。
不过对于最终用户来说,WDM驱动程序在Windows98和Windows2000下的表现很相似。
作为驱动开发人员来说,它在两者中有很多的不同。
并且Windows98中的WDM只能算是Windowss2000中的WDM的一个了集。
在Windows98中有一些驱动程序只能使用VXD来实现,如串行通讯驱动等。
要写驱动程序,首先要了解操作系统的结构。
在WDM体系中,windows2000操作系统中是最标准的实现方式,Windows98则是部分兼容WDM结构。
照微软的说法,Windows98和Windows2000 X86(Intel 架构)版本实现二进制码兼容(参见98DDK),Windows2000 x86版本与其它CPU平台版本实现源码级兼容(因为Windows 2000是基本NT相似的结构,最底层是硬件抽象层HAL,所有我们相信它们之间能源码级兼容)。
但实际上,Windows2000的WDM实现中有很多例程在Windows98中没有实现,一旦试图加载这样的WDM驱动程序到Windows98中,则不能正常加载,当然我们也有办法实现它,那就是利用“桩”技术。
具体可参见Walter Oney写的《Programming the Microsoft Windows Driver Model》一书。
我们首先来看看Windows 2000的系统结构,然后再来看看Windows 98的。
图一是Windows 2000的系统结构图。
从图中我们可以看出:整个系统被分为两个态,用户态和核心态。
从图中可以明显看出I/O操作最后是怎样作用到硬件上的。
用户态应用程序对Windows 子系统进行win32 API调用,这个调用由系统服务接口作用到I/O管理器(严格地说,在Windows 系统中不存在I/O管理器这样的独立模块,这个只是为了方便叙述而将各种核心功能调用的集合称作I/O管理器,业界人士都这样称呼这个部分),I/O管理器进行必要的参数匹配和操作安全性检查,然后由这个请求构造出合适的IRP(IO Request Package,I/O请求包),并把此IRP传给驱动程序。
简单情况下,驱动程序直接执行这个请求包,并与硬件打交道,从而完成I/O请求工作,最后由I/O管理器将执行结果返回给用户态程序。
但在WDM体系结构中,大部分实行分层处理。
即在图中“设备驱动“这部分,分成了若干层,典型地分成高层驱动程序、中间层驱动程序、底层驱动程序。
每层驱动再把I/O请求划分成更简单的请求,以传给更下层的驱动执行。
以文件系统驱动为例,最高层驱动只知道文件如何在磁盘上表示,但不知到怎样得到数据。
最低层驱动程序只知道怎样从磁盘取出512B为单的数据块,但不知道文件怎样表示。
举个更具体的生活例子。
主人(最高层驱动)知道(并且需要)笔计本电脑,但不知道具体放在什么位置;而仆人(最底层驱动)却知道它放在具体什么地方,但图一不知道(也不需要管)怎么使用。
在WDM驱动体系中,驱动尽可能被设计成分层并且通用的。
以USB驱动为例,USB 总线驱动负责与硬件打交道,但不负责数据的逻辑表示。
其它驱动程序只是扮演客户端驱动程序的角色,把各种请求转换成对USB总线驱动程序的请求。
比如我们使用的HID驱动中的键盘驱动程序(USB接口),我们按下键时,它只是简单(当然不是想象的那么简单,只是相对于USB总线驱动而言的)地把它转化为对USB总线驱动程序的请求,然后将USB总线驱动程序得到的结果返回系统中。
还有一类驱动程序就是我们常说的过滤器驱动程序。
它不负责完成基本的驱动任务,但它位其它驱动层次之间,并添加一些功能。
在设计过程中,有一个原则就是不影响其它层次的功能。
常见的例子是防火墙,底层实现其实是一种中间层过滤器驱动程序,负责检查IP 包的进出情况,允许合法的包通过,阻止非法的包通过。
最底层的驱动程序在收到IRP后,通过硬件抽象层,然后与硬件发生作用,从而完成I/O请求工作。
在这样的架构下,Windows 2000( or NT)上面的层就不需要对应每个操作系统都要开发一遍了。
所以微软认为在Windows2000 x86平台下开发的驱动和其它CPU平台下Windows 2000源码级兼容。
(试想一下,如果大家都用c写一个“hello world!”程序,那么只要有c编译器的操作系统平台下,运行的结果都是一致的。
)WDM驱动体系相对于Windows NT的KMD驱动体系不同之处在于它支持即插即用、拥有总线驱动和类驱动等等。
WDM驱动体系重新定义驱动程序层次,以便适应即插即用系统。
在这时我们引入了”驱动程序栈“的概念。
驱动程序栈是WDM驱动体系中驱动层次的有序集合。
可以这样理解:把各层次的驱动程序按一定顺序排列起来,各负责完成一定的功能。
具体可以看以下的图示:从图中我们可以看到,处于最下层的是总线驱动程序,上面是功能驱动程序。
在总线驱动程序和功能驱动程序之间还有可能出现过滤器驱动程序(中间层驱动)。
在某些特殊情况下有可能在第一个功能驱动程序层上出现几个另外的功能驱动程序。
总线驱动程序负责列举设备,也就是说,它负责发现总线上的所有设备并检测设备何时添加到总线上或何时从总线上删除。
总线驱动程序每发现一个设备就创建一个对应的物理设备对象。
一些总线驱动程序只是简单地控制对总线的访问权。
我们知道,一旦拥有总线权时,我们就可以完成我们想做的任何工作。
当然,大部分的总线驱动程序为我们完成这类总线上的所有任务。
功能驱动程序负责完成特定的功能,知道如何控制设备工作。
它在驱动程序栈中位于总线驱动程序上面。
功能驱动程序负责创建一个功能设备对象。
在USB 总线情形中,功能驱动程序必须使用总线驱动程序来访问它自己的设备。
在驱动程序栈中,可以插入各种类型的过滤驱动程序。
对于总线上的所有设备,总线过滤驱动程序被添加在总线驱动之上;而对于一个特定类的所有功能的功能驱动程序添加类过滤驱动程序。
设备过滤驱动程序仅对特定的设备添加。
上层的过滤驱动程序添加在功能驱动程序之上,而低层的过滤驱动程序添加在功能驱动程序下面。
在WDM 驱动体系中,为了实现上面所说的分层思想,也为了简化驱动程序的编写,预先提供了几种类驱动程序和总线驱动程序。
主要包括如下几类:一、人工输入设备(HID)类驱动程序人工输入设备类驱动程序提供输入设备的一个抽象接口。
实际的输入硬件可以使用不同的方法连接。
这些方法被HID 类驱动程序隐藏。
如果是USB 总线的人工输入设备,有可能要调用USB 总线驱动程序,但HID 类驱动提供给上层的接口是相同的,不因为底层接口的改变而有所不同。
二、静态图象体系静态图象体系结构(STI)根本上不是一种驱动程序,而是使用小类驱动程序获得扫描仪和静态图象相机图形数据的一种手段。
STI 目前支持SCSI 设备、串行设备、并行设备和USB 设备。
三、流类驱动程序流类驱动程序提供访问高带宽、时间关键的视频和音频数据的基础。
流类驱动程序使用小类驱动程序接口到实际的硬件。
我们可以编写中间过滤驱动程序来转换数据格式。
四、端口驱动程序音频端口驱动程序和小端口驱动程序用于控制实际的硬件。
通常由硬件制造商编写。
五、IEEE 1394总线驱动程序IEEE1394总线驱动程序列举并控制IEEE1394高速总线,这个总线驱动程序使用端口驱动程序访问IEEE1394硬件设备的控制电路。
IEEE1394客户驱动程序发出IEEE1394请求块IRB来控制它们自己的设备(这点上和USB驱动程序很相似的)。
六、USB总线驱动程序USB总线驱动程序列举并控制低速的USB总线设备。
主机控制器驱动程序(HOST设备)作为访问主要的两类USB主机控制器的标准。
USB客户驱动程序使用各种IOCTL通过USB类驱动程序访问它们自己的设备。
最主要的还是通过URB(USB请求块)来控制它们自己的设备。
七、SCSI和CDROM/DVD驱动程序SCSI和CDROM/DVD驱动程序用于访问硬盘、软驱、CDROM和DVD设备。
和上面的相似,提供各种端口驱动程序和小端口驱动程序来访各自的硬件设备。
例如:IEEE1394总线上的CDROM的请求会发送到IEEE1394总线驱动程序。
八、ACPIACPI(高级配置和电源管理接口)总线驱动程序与PC ACPI BIOS作用,列举系统中的设备并控制它们的电源使用。
九、PCI和PnPISA总线驱动程序它们和USB总线驱动相似,列举各自总线上的设备并控制它们。
PnPISA只对符合即插即用工业标准的ISA总线设备作这些工作。
还有一点必须明白,那就是I/O管理器向设备驱动程序栈发送的IRP是从栈顶进入的,理解这点很重要。
这样,当用户向I/O管理器请求了它要访问的功能设备时,I/O管理器将保证它的全部请求都发送到设备栈的顶部,这样处在设备驱动程序栈中的任何层次的过滤器驱动程序或功能驱动程序都得到首先处理这些请求的机会。
这就是WDM驱动程序的简单介绍。
上面我们主要讲述了Windows2000中的情形。
在Windows98中很相似,但由于它继承于windows95,所有不能够所有的设备都实现WDM体系结构。
有几种设备还只能使用VXD体系。
如串口驱动和文件系统驱动等。
从上面我们已经知道wdm究竟是怎么回事,接下来让我们看看在Windows2000操作系统中有哪些驱动程序。
请见图三。
∙虚拟设备驱动程序(VDD)是一个用户模式部件,它可以使DOS应用程序访问x86平台上的硬件。
VDD通过屏蔽I/O权限掩码来捕获端口存取操作,它基本上是模拟硬件操作,这对于那些直接对裸机硬件编程的应用程序特别有用。