WDM驱动程序设计之设计开发篇


(作者:苏金国 2000年11月09日 13:26)

通过安装DDK和相应的开发软件,我们构造好了WDM驱动程序的开发环境。接着,我们就要深入进行设计与开发工作了。
  ■WDM 驱动程序的运作流程

  WDM本身的PNP管理器被抽象地提升到了ROOT的地位。PNP管理器负责所有的总线驱动程序的加载。总线驱动程序则负责遍历所有位于总线上的设备,并且为每个设备创建相应的设备对象。当PNP管理器发现一个设备对象,就查找该对象对应的Driver。并调用该Driver的ADD DEVICE例程。如果Driver不在内存中,就先加载,然后调用ADD DEVICE例程。

  当然,总线本身并没有发出任何信号告诉PNP管理器自己的存在,所以,总线Driver是在NT的安装时设定的。而ISA设备并没有规范,因为需要KMD自己检查硬件存在及状态,所以它是老式KMD存在的惟一理由。这也是微软极力在新规范里取消ISA总线的理由之一。WDM支持PNP协议和PM协议,而且实现时仅仅需要在MAJOR FUNCTION里加入一些对PNP和PM事件响应的例程即可。

  ■驱动程序设计

  设计一个设备驱动程序,应该支持和其他相同类型设备的NT驱动程序相同的IRP_MJ_XXX和IOCTL请求代码。如果设计一个中间层NT驱动程序,应该首先确认下层驱动程序所管理的设备,因为一个高层的驱动程序必须具有低层驱动程序绝大多数IRP_MJ_XXX例程入口。高层驱动程序在接到I/O请求时,在确定自身IRP当前堆栈单元参数有效的前提下 ,设置好IRP中下一个低层驱动程序的堆栈单元,然后再调用IoCallDriver将请求传递给下层驱动程序处理。一旦决定好了驱动程序应该处理哪些IRP_MJ_XXX,就可以开始确定驱动程序应该有多少个Dispatch例程。当然也可以考虑把某些RP_MJ_XXX处理的例程合并为同一例程处理。例如在ChangerDisk和VDisk里,对IRP_MJ_CREATE和IRP_MJ_CLOSE处理的例程就是同一函数。

  一个驱动程序必须为它所管理的每个可能成为I/O请求的目标的物理和逻辑设备创建一个Device对象。一些低层的驱动程序还可能要创建一些不确定数目的Device对象。例如一个硬盘驱动程序必须为每一个物理硬盘创建一个Device对象,同时还必须为每个物理磁盘上的每个逻辑分区创建一个Device对象。

  一个高层驱动程序必须为它所代表的虚拟设备创建一个Device对象,这样更高层的驱动程序才能连接它们的Device对象到这个驱动程序的Device对象。另外,一个高层驱动程序通常为它低层驱动程序所创建的Device对象创建一系列的虚拟或逻辑Device对象。

  尽管可以分阶段来设计驱动程序,从而使一个处在开发阶段的驱动程序不必一开始就创建出所有它将要处理的所有Device对象,但从一开始就确定好最终要创建的所有Device对象将有助于设计者所要解决的任何同步问题。另外,确定所要创建的Device对象还有助于定义Device对象的Device Extension的内容和数据结构。

  ■驱动程序开发

  驱动程序的开发是一个从粗到细逐步求精的过程。NT DDK的src/目录下有一个庞大的模板代码,几乎覆盖了所有类型的设备驱动程序、高层驱动程序和过滤器驱动程序。在开始开发驱动程序之前,应该先在这个样板库下面寻找是否有和所要开发的类似类型的例程。

  例如若要开发光盘塔驱动程序,虽然DDK对光盘塔没有任何描述,但光盘塔是符合SCSI-Ⅱ规范的SCSI设备,可以在src/storage/class目录中发现很多和SCSI设备有关的驱动程序,例如SCSI Tape、SCSI Disk、SCSI CDROM等驱动程序开发时,可以参考类似驱动程序,从而减化开发难度。

  下面笔者将进一步介绍开发驱动程序的基本步骤:

  l.编写驱动程序框架

  (1)首先编写一个DriverEntry例程,并在该例程里调用IoCreateDevice来创建一个Device对象。

  (2)写一个处理IRP_MJ_CREATE请求的Dispatch例程的基本框架。如果驱动程序创建了多于一个的Device对象,则必须为IRP_MJ_CLOSE请求写一个例程,该例程通常情况下可以和DispatchCreate共用一个例程。

  (3) 编译连接驱动程序。

  2.测试驱动程序

  (1)首先在系统中安装好驱动程序,具体编译安装驱动程序请见下版的《编译安装篇》。

  (2)为NT逻辑设备名称和目标Device对象名称之间建立起符号连接,在前面已经知道Device对象名称对Win32用户模式是不可见的,是不能直接通过API来访问的,Win32 API只能访问NT逻辑设备名称。可以通过修改注册表来建立这两种名称之间的符号连接。运行Regedt32.exe在/HKEY_LOCAL_MACHINE/ System/ CurrentControlSet/ Control/ Session Manager/ DOS Devices下建立起符号连接,这种符号连接也可以在驱动程序里调用函数IoCreateSymbolicLink来创建。

  (3)完成以上所有的设置并检查无误后,我们必须重新启动Windows系统。

  (4)编写一个简单的测试程序调用Win32 API中的CreateFile函数,并以刚才命名的NT逻辑设备名打开这个设备。如果打开成功,则成功地写出了一个最简单的驱动程序了。支持更多的设备I/O请求,例如驱动程序可能需要对IRP_MJ_READ请求做出响应(完成后可用ReadFile 函数进行测试)。如果驱动程序需要能够手工卸载,那么还必须对IRP_MJ_CLOSE做出响应。为所需要处理的IRP_MJ_XXX写好处理例程,并在DriverEntry里面初始化好这些例程入口。一个低层的驱动程序需要一个StartIo、ISR和DpcForIsr例程,可能还需要一个SynchCritSection例程,如果设备使用了DMA,那么可能还需要一个AdapterControl例程。

  对于高层驱动程序可能需要一个或多个IoCompletion例程,最起码完成检查I/O状态块然后调用IoCompleteRequest的工作。如果需要,还要对Device Extension数据结构和内容做些修改。有一点必须很清楚的,就是代码运行级别的问题,即IRQL,最常见的级别是PASSIVE_LEVEL、APC_LEVEL、DISPATCH_LEVEL和DIRQL。

  在看NT DDK HELP中的函数说明的时候,要注意函数的可运行级别,比如有的函数只能在PASSIVE_LEVEL下运行,有的函数则可以在DISPATCH_LEVEL以下级别运行,级别越高的时候,对代码的要求就越严格,比如在DISPATCH_LEVEL的时候,就不能使用分页内存。通常情况下应该尽可能让代码在低运行级别如PASSIVE_LEVEL下运行,在高级别下运行过长时间将导致系统效率降低、影响系统响应的实时性。但有时候自己无法控制运行的级别,例如在调用低层Driver时使用IoCallDriver,低层Driver响应完毕后会执行completion例程,该例程运行的级别就是由低层Driver来决定。因此在编写completion例程时,应尽量将这个函数设计成能在DISPATCH_LEVEL级别运行。

  依照以上开发步骤,我们可以设计出全新的WDM设备驱动程序。

  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
第一章概述...........................................................................................................................6 1.1 本教程的规划:...............................................................................................................6 第二章WDM驱动程序的运行.................................................................................................7 2.1 WDM驱动程序的基本调用流程:.....................................................................................7 2.1.1驱动程序何时从何处开始执行?........................................................................7 2.1.1.1第一次安装好驱动程序:................................................................7 2.1.1.2驱动程序正常运行:........................................................................7 2.1.2 DriverEntry()大约做些什么?.........................................................................7 2.1.2.1 IRP主功能码(Major Function Code).......................................9 2.1.2.2 IRP_MJ_PNP次功能码(Minor Function Code).......................10 2.1.2.3 IRP_MJ_POWER次功能码(Minor Function Code)...................10 2.1.3驱动程序与应用程序相关的功能码如何调用?..............................................10 2.1.3.1 DriverEntry()中您必须要注册回调函数...................................10 2.1.3.2 在您的应用程序中正确调用CreateFile().............................11 2.1.3.3 应用层调用驱动的消息参照:.....................................................11 2.1.3.4 IoControl调用:...........................................................................11 第三章开始编写WDM驱动程序...........................................................................................13 3.1 得到一个Demo工程:.....................................................................................................13 3.2 在VC下配置DDK的开发环境...........................................................................................15 3.2.1 我的目录.............................................................................................15 3.2.1.1我们应该在系统环境变量里设置..................................................15 3.2.2安装VC6................................................................................................17 3.2.3 打开wdm1\sys\Wdm1.dsp工作区文件...............................................18 3.2.4 修改H:\driverDev\MakeDrvr.bat文件...........................................18 3.2.5 设置VC的环境.....................................................................................19 3.2.5.1前面的内容编译时出了错误(配置'MakeDrvr')......................19 3.2.5.1.1 在project -> settings中设置成如下:.......................19 3.2.5.1.2 还可以在Tools-> Options-〉directories中选择“Executable files”并添加MakeDrvr.bat的目录即可.................20 3.2.5.1.3 再按F7编译 有编译提示..................................................20 3.2.5.1.4 搞清楚 MakeDrvr.BAT文件的功能...................................21 3.2.5.2前面的内容编译时出了错误,让我们看看是什么原因..............22 第四章 安装DebugPrintMonitor驱动程序.................................................................................24 4.1 用控制面板安装DebugPrintMonitor...........................................................................24 4.2 检查DebugPrint driver的安装情况...........................................................................29 第五章 安装wdm1驱动程序..........................................................................................................30 5.1 INF 文件.........................................................................................................................30 5.1 全新安装驱动.................................................................................................................30 5.1.1 安装驱动WDM1.SYS.............................................................................................30 5.2 测试DebugPrintMonitor...............................................................................................30 第六章 执行应用程序...................................................................................................................32 6.1 打开Wdm1Test.dsp.........................................................................................................32 6.2 编译Wdm1Test 工程.......................................................................................................32 6.3 修改Wdm1Test .CPP文件的setupapi.h的路径...........................................................33 6.3 重新指定Wdm1Test 工程的setupapi.lib的路径.......................................................35 6.4 类型DWORD_PTR和ULONG_PTR没定义的错误.................................................................36 6.4 调试WdmTest工程...........................................................................................................37 6.4.1 设置断点.............................................................................................................37 6.4.2 单步执行.............................................................................................................38 6.4.3 SYS目录下驱动程序代码对照:.......................................................................40 6.4.4 EXE中继续往下执行ReadFile/WriteFile.......................................................40 6.4.4.1 执行ReadFile的情况.............................................................................40 6.4.4.2 执行WriteFile的情况...........................................................................42 6.4.5其他的请自己执行..............................................................................................43 第七章 启用wdm1驱动程序..........................................................................................................44 第八章 停用wdm1驱动程序..........................................................................................................45 8.1 点击“我的电脑” –〉“属性” –〉“硬件”.........................................................45 8.2 点击 “设备管理器”并展开其他设备.......................................................................45 第九章还有更好的DebugView.exe.............................................................................................47 9.1得到DebugView.exe.........................................................................................................47 9.2 原理..................................................................................................................................48 9.2.1 DBG.......................................................................................................................48 9.2.2 DbgPrint().........................................................................................................48 9.2.3 如何使用DbgPrint()........................................................................................48 9.2.4 修改wdm1工程的例子........................................................................................48 9.3 如何使用DebugView.......................................................................................................48

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值