newcreater的个人空间 https://blog.eetop.cn/244251 [收藏] [复制] [分享] [RSS]

空间首页 动态 记录 日志 相册 主题 分享 留言板 个人资料

日志

Windows2000设备驱动程序的研制开发

已有 874 次阅读| 2008-9-20 11:40

Windows2000设备驱动程序的研制开发              

来源:  作者:许永利

引言:

由于工作关系,我经常涉及PC机与外围设备接口的工作,从PC机这方面要做的工作看来,主要是通过接口处理外围设备的中断,通过I/O端口或内存地址与外设互相传递数据。从 计算 机原理的角度看,所要达到的目的很简单,那么如何编写程序完成上述功能呢?

目前 国内流行的PC操作系统有三种:DOSWin95/98系列,WindowsNTDOS是单用户、单任务操作系统,由于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 三种操作系统下访问接口比较

操作系统

应用程序访问接口方式

访问权限

DOS

直接访问

所有[]

Windows95/98

通过设备驱动程序*.VXD

所有[]

直接访问

I/O端口

WindowsNT

通过设备驱动程序*.SYS

所有[]

[]‘所有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管理器根据需要调用这些函数,对于一个需要处理中断的最简单的驱动程序也需要由以下几个函数构成:

1.DriverEntry()
运行于PASSIVE_LEVEL
驱动程序入口点,当驱动程序被手动或自动装入系统后,驱动程序从这点开始执行,主要用于定位硬件资源,建立指向其它驱动程序函数的指针等其它初始化工作。

2.XxUnload()
运行于PASSIVE_LEVEL
用于驱动程序从系统卸出之前,释放由驱动程序占用的所有系统资源。

3.XxIsr()
运行于DIRQL
中断服务程序。

4.XxDpcForIsr()
运行于DISPATCH_LEVEL
中断服务程序后处理程序,以排队方执行不太关键代码的执行,由于排队机制及优先级,不会造成代码拥塞从而提高中断服务程序的响应并且提高系统总体I/O吞吐率。

5.XxOpen()
运行于PASSIVE_LEVEL
处理应用程序Win32函数CreateFile()请求。

6.XxClose()
运行于PASSIVE_LEVEL
处理应用程序Win32函数CloseHandle()请求。

7.XxDispatch()
运行于PASSIVE_LEVEL
处理应用程序Win32函数DeviceIoControl()请求,通过一系列自定义命令,驱动程序与应用程序交换特定的信息。

WindowsNT
使用一个抽象化的cpu优先级方案, IRQL代表中断请求级,任一时刻CPU总处在某一级上,这个数越大,表示当前的任务重要性越大,如表2-1所示,从上至下IRQL越来越小。所有上述驱动程序的函数及内核模式函数都必须运行于各自的IRQL级上,如果违反这一调用规定,会造成系统崩溃。例如,中断服务程序(XxIsr)运行于DIRQL及上,那幺在编写中断服务程序时,只能调用允许在这一级运行的内核模式函数(并不是所有内核模式函数都能运行于DIRQL)。至于每个内核模式函数运行级别的说明,详见[2]Kernel-Mode Drivers-Reference章节。

WindowsNT
是一多任务系统,许多设备的驱动程序同时存在系统中,这样各个设备所占用的资源(中断,I/ORAM地址空间)很有可能冲突,如果设备驱动程序在运行之前不进行探测而使用自己硬件设备的资源,有可能和系统内其它设备占用的资源冲突,后果不堪设想。WindowsNT通过注册表管理硬件资源的占用信息,作为内核模式信任的组件,驱动程序使用硬件资源之前必须遵循查询-申请-使用-释放的原则(如图2-2所示)

2-1

来源

IRQL

硬件

HIGHEST_LEVEL

POWER_LEVEL

IPI_LEVEL

CLOCK2_LEVEL

CLOCK1_LEVEL

PROFILE_LEVEL

DIRQLs(I/O设备中断平台相关的级数)

软件

DISPATCH_LEVEL

APC_LEVEL

PASSIVE_LEVEL

WindowsNT设备驱动程序的编写步骤与实例
现以一实际例子简要说明设备驱动程序的开发步骤,本例以CINRAD天气雷达测试卡实际应用为原型,加以简化、抽象。

第一步,了解被控设备的接口情况。

本例为一ISA卡,占用PC9号中断,I/O地址360HRAM地址D0228H分别一个字空间。

第二步,确定驱动程序的功能。

驱动程序每当9号中断达到时,检查运行标志变量RunFlag(为一BOOL变量),如果等于TRUE,中断累积计数器counter(为一unsigned short变量)增一,把这个值写入RAM地址D0228H,再从这个地址读出,如果读出值等于写入值,把这个值写入I/O地址360H,这个地址的 内容 会驱动板卡上的LED显示,把写入值显示出来;如果读出值不等于写入值,设置运行标志变量FALSE。如果运行标志变量等于FALSE,什幺也不做,返回。

第三步,定义驱动程序与 应用 程序的软件接口。

本例定义两个接口命令:

IOCTL_IOCardA_START:
应用程序设置驱动程序内部的运行标志变量等于TRUE
IOCTL_IOCardA_READ:
应用程序查询驱动程序内部的中断累积计数器的值。
第四步,画流程图。这里列举本例实现的几个主要流程图,(图略)。

系统传给驱动程序入口函数系统定义的设备驱动对象’DrObj,通过初始化这个对象的一些成员变量,把驱动程序其它函数与这个对象联系起来。
ISA
卡为非即插即用设备,事先把资源占用信息手工添加注册表如下:
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\IOCardA\parameters]

"IRQ"=dword:00000009

"IOSPAN"=dword:00000004

"IOAdd"=dword:00000360

"RAMAdd"=dword:000d0228

"RAMSPAN"=dword:00000002

其中IOCardA以下各子键及其值为自定义,设备驱动程序利用相应函数检索出这些值。

(3)
每个设备驱动程序可以创建若干系统定义的设备对象,本例根据需要只创建了一个设备对象’Dev设备对象其中一个成员变量为指向一非分页的物理内存块DeviceExtension,这块内存大小及内容为用户自定义,由于DevDeviceExtension对象会被系统传给驱动程序的其它函数,这样驱动程序各函数通过访问这块内存区,实际上达到互相传递信息的功能。本例在这里存储设备硬件资源信息及RunFlag和中断计数器counter,这些数值在DriverEntry()初始化后,供驱动程序的其它函数使用。

3-2为中断服务程序


点赞

评论 (0 个评论)

facelist

您需要登录后才可以评论 登录 | 注册

  • 关注TA
  • 加好友
  • 联系TA
  • 0

    周排名
  • 0

    月排名
  • 0

    总排名
  • 0

    关注
  • 1

    粉丝
  • 0

    好友
  • 0

    获赞
  • 0

    评论
  • 158

    访问数
关闭

站长推荐 上一条 /2 下一条


小黑屋| 手机版| 关于我们| 联系我们| 隐私声明| EETOP 创芯网
( 京ICP备:10050787号 京公网安备:11010502037710 )

GMT+8, 2025-1-7 10:23 , Processed in 0.022161 second(s), 13 queries , Gzip On, Redis On.

eetop公众号 创芯大讲堂 创芯人才网
返回顶部