Windows2000 设备驱动程序的研制开发
引言
由于工作关系,我经常涉及 PC 机与外围设备接口的工作,从 PC 机这方面要做的工作看
来,主要是通过接口处理外围设备的中断,通过 I/O 端口或内存地址与外设互相传递数据
。从 计算 机原理的角度看,所要达到的目的很简单,那么如何编写程序完成上述功能呢
? 目前 国内流行的 PC 操作系统有三种:DOS,Win95/98 系列,WindowsNT。DOS 是单
用户、单任务操作系统,由于 PC 机硬件处理速度不断提高,基于单用户、单任务的操作
系统越来越不能充分发挥硬件的功能,现在只 应用 于一些老式 PC 及其它个别场合,有
逐渐被淘汰的趋势;Win95/98 系列和 WindowsNT 属于多任务操作系统,不论从其原理
还是界面上看,这两种操作系统都比 DOS 有着无可比拟的优越性,这两种操作系统虽然
在界面和操作上及其相似,但其内部实现的诸多方面有许多区别,有些区别是本质上的。
Win95/98 设计目标是针对一般家庭用户,安全性及可靠性存在许多薄弱环节,就可靠性
而言,Win95/98 系列不能很好的防止多任务环境中某个进程的非法操作导致系统中其它
程序甚至整个系统的崩溃,而 WindowsNT 在这方面及其它诸多方面设计的相当严谨。这
两种操作系统是 Microsoft 公司同一时期的产品,但针对不同的使用群,所以在一些重要
场合及生产实践中应该选择 WindowsNT 作为计算机的操作系统,此外,从 发展 趋势来看
,WindowsNT 已经成为定型产品,具有相对稳定性。在不同操作系统下编写驱动程序是有
很大区别的,在 DOS 平台上,应用程序和设备驱动程序之间没有标准的接口,它们在外
部表现为一个扩展名为 EXE 的文件,驱动程序的作用被柔和在应用程序中,这样,应用程
序为了使用不同厂商的同一类设备,必须了解这些设备在接口上具体的硬件实现,同时,
对于一个特定型号的硬件产品,所有支持它的应用软件中对于控制整个设备动作的这部分
代码,可能被多次重写。这种情况不适应硬件及应用软件的飞速发展。Windows 系统在这
方面,进行了根本性改进,把控制设备动作的这部分代码独立出来,提出了设备驱动程序
的概念,驱动程序是应用程序和硬件设备之间的一个桥梁,应用程序与驱动程序之间有明
确的接口,应用程序通过与驱动程序交换信息,达到控制外设的目的。接口定义的操作是
面向设备的,这就是说,在应用程序的设计中,并不用关心对外设操作的具体硬件实现,
只是对驱动程序发出一系列指令既可;驱动程序接受来自上层应用程序的指示,具体操纵
实际硬件,完成用户功能。具体实现上,Win95/98 系列与 WindowsNT 又有所区别,
WindowsNT 是严格按照上述思路设计的;而 Win95/98 系列不那么严格,其支持上述思
路,但同时应用程序也可以绕过驱动程序直接访问实际物理 I/O,这样做,增加程序设计
的灵活性,但同时,对系统可靠性造成一定隐患。这也正是 Win95/98 系列可靠性低于
WinNT 的原因之一。表 1-1 三种操作系统下访问接口比
[注]‘所有’指 I/O 端口,RAM 总线,中断,DMA。WindowsNT 设备驱动程序的组成原
WindowsNT 操作系统结构分为用户模式和内核模式,用户模式下的编程为应用程序的设计
,而开发设备驱动程序,则属于内核模式下的编程,内核模式组件包括 NT
Executive(ExXxx),内核(KeXxx),硬件抽象层(HalXxx)。其层次如图 2-1 所示,其中 NT
Executive 包括几个独立的软件组件,它们是系统服务接口(ZwXxx),对象管理器(ObXxx),
配置管理器,进程管理器(PsXxx),安全监视器(SeXxx),虚拟空间管理器(MemXxx),本地
进程调用,I/O 管理器(IoXxx)。内核模式的系统服务并不是全部公开的,而是提供了一系
列开发设备驱动程序需要的函数(上文括号内为函数形式,函数手册参见[2]Kernel-Mode
Drivers-Reference 章节),换言之,这些函数功能是所有内核模式的系统服务功能的子集
。驱动程序由一系列相对独立的函数组成,由 I/O 管理器根据需要调用这些函数,对于一
个需要处理中断的最简单的驱动程序也需要由以下几个函数构成:() 运行于
PASSIVE_LEVEL 驱动程序入口点,当驱动程序被手动或自动装入系统后,驱动程序从这点
开始执行,主要用于定位硬件资源,建立指向其它驱动程序函数的指针等其它初始化工作
。() 运行于 PASSIVE_LEVEL 用于驱动程序从系统卸出之前,释放由驱动程序
占用的所有系统资源。() 运行于 DIRQL 中断服务程序。() 运行于
DISPATCH_LEVEL 中断服务程序后处理程序,以排队方执行不太关键代码的执行,由于排
队机制及优先级,不会造成代码拥塞从而提高中断服务程序的响应并且提高系统总体 I/O
吞吐率。() 运行于 PASSIVE_LEVEL 处理应用程序 Win32 函数 CreateFile()请求。
() 运行于 PASSIVE_LEVEL 处理应用程序 Win32 函数 CloseHandle()请求。
() 运行于 PASSIVE_LEVEL 处理应用程序 Win32 函数 DevicEioControl()请求,
通过一系列自定义命令,驱动程序与应用程序交换特定的信息。WindowsNT 使用一个抽象
化的 CPU 优先级方案, IRQL 代表中断请求级,任一时刻 CPU 总处在某一级上,这个数越
大,表示当前的任务重要性越大,如表 2-1 所示,从上至下 IRQL 越来越小。所有上述驱
动程序的函数及内核模式函数都必须运行于各自的 IRQL 级上,如果违反这一调用规定,
会造成系统崩溃。例如,中断服务程序(XxIsr)运行于 DIRQL 及上,那幺在编写中断服务程
序时,只能调用允许在这一级运行的内核模式函数(并不是所有内核模式函数都能运行于
DIRQL 级)。至于每个内核模式函数运行级别的说明,详见[2]Kernel-Mode Drivers-
Reference 章节。WindowsNT 是一多任务系统,许多设备的驱动程序同时存在系统中,这
样各个设备所占用的资源(中断,I/O 及 RAM 地址空间)很有可能冲突,如果设备驱动程序
在运行之前不进行‘探测’而使用自己硬件设备的资源,有可能和系统内其它设备占用的资
源冲突,后果不堪设想。WindowsNT 通过注册表管理硬件资源的占用信息,作为内核模式
信任的组件,驱动程序使用硬件资源之前必须遵循‘查询-申请-使用-释放’的原则(如图 2-2
所示)。表 2-
WindowsNT 设备驱动程序的编写步骤与实例 现以一实际例子简要说明设备驱动程序的开
发步骤,本例以 CINRAD 天气雷达测试卡实际应用为原型,加以简化、抽象。第一步,了
解被控设备的接口情况。本例为一 ISA 卡,占用 PC 机 9 号中断,I/O 地址 360H 及 RAM
地址 D0228H 分别一个字空间
WindowsNT 是一个复杂而严密的系统,驱动程序的开发不可避免的涉及 现代 操作系统 理
论 及其它许多计算机理论,内涵相当广泛,本文围绕着开发实践从一定深度探讨了
WindowsNT 设备驱动程序开发最基本的知识及一般 方法 ,希望对读者有所帮助,对于复
杂,特殊应用的实现及编程技巧,有待于读者在各自实际应用中不断探索。 参考 文献
1.《WindowsNT 设备驱动程序设计指南》 Art Baker 著 机械 工业 出版社 Co.
WindowsNT Device Driver Kid