驱动开发学习笔记2.docx
精品名师归纳总结资料word 精心总结归纳 - - - - - - - - - - - -驱动开发学习笔记1很久没有网了,出了一段时间的差,近来,莫名的就有点郁闷!前不久在大富翁上发了 一份帖子是关于delphi程序员的进展,大家的反应并不都是很好。于是开头觉得可以考虑换个方向。以前我是做MIS开发的。换哪个方向了?人越多的方向,似乎越是没有前途。想想起初上高校,那可是越多人考的学校,学费越贵啊!可现在的职业了?越 多人干的事,越是没有前途了。考虑来考虑去,打算学习一下驱动程序的开发吧!于是 从网上查找了一些资料,看的懂的觉得蛮不错适合我这种学校生的就贴了出来,算是学习笔记吧!用户模式与内核模式从 Intel80386开头,出于安全性和稳固性的考虑,该系列的CPU 可以运行于ring0ring3从高到低四个不同的权限级,对数据也供应相应的四个爱护级别。运行于较低级别的代码不能随便调用高级别的代码和拜访较高级别的数据,而且也只有运行在 ring0层的代码可以直接对物理硬件进行拜访。由于WindowsNT是一个支持多平台的操作系统,为了与其他平台兼容,它只利用了CPU 的两个运行级别。一个被称为内核模式 ,对应 80x86的 ring0层,是操作系统的核心部分,设备驱动程序就是运行在该模式下。另一个被称为用户模式 ,对应 80x86的 ring3层,操作系统的用户接口部分(就是我们通常所说的win32 API)以及全部的用户应用程序都运行在该级别。 操作系统对运行在内核模式下的代码是不设防的,所以不管是建设仍是破坏内核模式下的编程都是值得去讨论的。图 1-WIN2000系统的分层结构在物理硬件与系统核心之间有一个硬件抽象层(HardwareAbstractionLayer),它屏蔽了不同平台硬件的差异,向操作系统的上层供应了一套统一的接口。从图中我们仍 可以看到,设备驱动程序(DeviceDriver)是被 I/O治理器 I/OManager包围起来的,即驱动程序与操作系统上层的通信全部都要通过I/O治理器。 这给驱动程序的编写带来了很大的便利,由于许多诸如接收用户的恳求、与用户程序交换数据、内存映射、挂接中断、同步等等麻烦的工作都由I/O治理器代劳了。驱动程序的分类驱动程序并不像全部人想的那样肯定要和硬件打交道,我粗略的把他分为两类:硬驱动和软驱动。 硬驱动就是对硬件直接编程进行掌握,这类驱动通常必需遵守硬件的通信协议,直接对硬件进行端口拜访、中断响应、DMA 传输。它包括:串、并行口,键盘,文件系统, SCSI ,网络等驱动程序。另外一种软驱动了?不需要直接对硬件就行操作。我认为他可以懂得为它是在硬驱动之上的一层更为高级的驱动。我想学习的主要是软驱动。一般来说,设备驱动程序的任务主要有两个:第一,接受来自用户程序的读写恳求,把用户的数据传送给设备,或把从设备接收到的数据传送给用户。其次,轮询设备或处理来自设备的中断恳求,完成数据传输。驱动程序的结构可编辑资料 - - - 欢迎下载精品名师归纳总结学习资料 名师精选 - - - - - - - - - -第 1 页,共 19 页 - - - - - - - - - -可编辑资料 - - - 欢迎下载精品名师归纳总结资料word 精心总结归纳 - - - - - - - - - - - -在这里,我主要介绍WDM的结构。WDMWindows driver module是什么东西了? 在 Windows9895下面,或许你听得最多的是VXD ,我只知道VXD 是一种驱动程序,和 WDM 差不多的东西。 只是由于 Windows2000是 WindowsNT那条线过来的东西,要加上两个主要的新功能:即插即用(Plug and Play)和电源治理( Power Menage),又不能用 Windows9895那一套, 所以就搞出一个叫WDM这么个东西, 来支持 PNP和 PM. 。其实想想,现在的技术名词仍不是一般的多啊!总之wdm大家都叫它windows驱动程序模型 。Windows2000里有叫 即插即用治理器和 IO(此 IO非彼 IO端口)治理器 的两个东西。比如说我在机器上插了一张符合PCI 规范的 PCI 卡。即插即用治理器会发觉 这张卡插在第N 个插槽上, 然后即插即用治理器会说它找到了这样一张卡,它就去找有没有现成的驱动程序,假如没有找到,它会告知我们,我找到了这样一张卡,请你插入这张卡的驱动程序盘。好,我们就把驱动程序盘给它,即插即用治理器会去找驱动程序盘上的 INF文件,找到后它会比较PCI 卡上的标志和INF 文件里的标志是否相同,假如相同,它就会依照INF文件里供应的路径去找驱动程序,找到之后就可以交给IO 治理器, IO治理器会装载这个驱动程序。 IO治理器在做了一些接口的工作后,即 插即用治理器会先安排好相关的资源给PCI 卡,比如说IO端口空间、内存空间和中断向量,然后告知这张卡的驱动程序,我给你安排了这些资源,你看怎么的。假如你没有怎么的或不敢怎么的,那就赶快登记这些资源,以备后用。下面说 IO治理器这个东西。上面我们讲到IO治理器装载这个驱动程序,驱动程 序有一个大门,仍有N 多的小门。 IO治理器先从大门进去(由于IO治理器只找得 到大门, IO治理器是不是很傻,NO ,当然有它的道理,你别问我:IO治理器怎么 找到大门的?驱动程序无非就是一些文件,IO治理器把这么些文件加载到系统中去), 去找一样东西:进小门的的图。我们要在大门进去的房间里放这张的图(驱动程序都是我们造的,我们当然有驱动程序的的图啦)。IO治理器找到了的图,就可以自由进出大小门了。 这些大小门说白了就是函数(不要问我函数是什么东东),小门的的图就是函数的的址。IO治理器知道了这些函数的的址,当然就可以调用这些函数啦。 仍有一个叫IRP的东西,中文名叫IO恳求包。我们这样来懂得它:在用户的应用程序这一端,要和驱动程序对话,它们之间不是简洁的调用函数(至于为什么,我现在也不知道),应用程序和驱动程序之间有IO治理器隔着,应用程序对驱动程序的操作, 第一由 IO治理器处理成一个包,这个包里面有应用程序恳求的操作内容、传送的数据等等一些东西, 然后 IO治理器把这个包扔给驱动程序,驱动程序依照包里的恳求,完成操作,把该回传的数据放进包里,再把包扔仍给IO治理器, IO治理器再把数据返回给应用程序。 这里所说的包,就是IRP 。这里说的只是WDM结构的一部分, 但是有了这一部分学问,其它部分就不难懂了。通过上面的介绍你观察了什么。你可以想象得出驱动程序是什么样子的吗?我是这样想的。驱动程序似乎就是一个函数库,只不过在大门的的方放了一张的图。而这个大门与的图我们见到过吗?似乎有点像dll 文件了。在早些时候我学dll 的时候,我就只会用dll 来存放函数。2005年 9 月 24 日 13:57可编辑资料 - - - 欢迎下载精品名师归纳总结学习资料 名师精选 - - - - - - - - - -第 2 页,共 19 页 - - - - - - - - - -可编辑资料 - - - 欢迎下载精品名师归纳总结资料word 精心总结归纳 - - - - - - - - - - - -驱动程序开发 工具篇由于我学习的时候是在win2000下进行的,所以一切以我学习时的配置为准。第一:安装win2000操作系统,我安装是win2000高级服务器版本。其次:安装Vc+6.0,我装的是英文版。第三:安装win2000DDK。通常驱动程序的调试都是用ddk在 cmd中完成的。这部分我临时略过。下面先介绍如何设置 vc+6.0在 Visual Studio 6.0集成环境中开发设备驱动程序的方法。在 Windows上,Windows DDK供应的开发环境是基于命令行的,操作起来极为不便,而 Visual Studio 6.0给我们供应了特别友好易用的集成环境,让我们有如虎添翼之感。那么,能否利用Visual Studio的集成环境来开发驱动程序了?答案是可以的。通过对 Visual Studio集成环境的简洁设置,创建好自己的驱动开发集成环境就可 以了。第一要求系统已安装DDK 和 Visual C+6.0安装时选上全部工具 ,1、接下来需要改造ddkbinsetenv.bat把要求 mstools的有关语句注释掉 如想在命令行环境开发驱动就仍需加入call VC_DIRVC98BinVcvars32.bat,以便能在命令行使用vc 的相关工具。如只想在IDE 环境开发就不必调用Vcvars32.bat,由于相关工具的路径信息可以在vc 环境中设置 .2、创建一个目录DriverEnv(目录名随便), 作为你开发驱动的大本营3、在该目录下创建一个批处理文件MakeDrvr.bat,内容如下:echo offif "%1"="" goto usage if "%3"="" goto usageif not exist %1binsetenv.bat goto usage call %1binsetenv %1 %4%2cd %3build -b -w %5 %6 %7 %8 %9 goto exit:usageecho usage MakeDrvr DDK_dir Driver_Drive Driver_Dir free/checked build_optionsecho eg MakeDrvr %DDKROOT% C: %WDMBOOK% free -cef:exit可编辑资料 - - - 欢迎下载精品名师归纳总结学习资料 名师精选 - - - - - - - - - -第 3 页,共 19 页 - - - - - - - - - -可编辑资料 - - - 欢迎下载精品名师归纳总结资料word 精心总结归纳 - - - - - - - - - - - -该批处理第一对传递的参数作一些检查,然后调用 ddk的 setenv命令设置环境变量,然后转变目录为源程序所在驱动器和目录,并最终调用build, -b保证显示完全的错误信息, -w 保证在屏幕上输出警告,在vc ide里的 output窗口中可以看到这些错误和警告。4. 建立一个空白工程选 File的 new 菜单项 , 然后选 project栏的 makefile,然后输入路径,一路next下去即可 ,visual studio供应两种配置win32 debug和 win32 release.5. 修改这两种配置选 project的 settings菜单项 win32 debug:在 Build Command Line一栏填入MakeDrvr DDK_DIR SOURCE_DRIVE SOURCE_DIR checked build option s在 Rebuild all options一栏填入-nmake /a在 output file一栏填入与sources文件中的 TARGETNAME相同的文件名在 Browse info file name一栏填入 obji386checked与TARGETNAME相同的文件名,见下述).bscwin32 release:在 Build Command Line一栏填入MakeDrvr DDK_DIR SOURCE_DRIVE SOURCE_DIR free build options在 Rebuild all options一栏填入-nmake /a在 output file一栏填入与sources文件中的 TARGETNAME相同的文件名在 Browse info file name一栏填入 obji386free与 TARGETNAME相同的文件名 .bsc注: DDK_DIR 一般可以写成 %BASEDIR%, build options一般为 -cef即已足够6. 添加源文件到工程可以新建,也可以添加,这和一般的win32开发一样。7. 添加资源文件选 INSERT的 RESOURCE菜单项即可8. 把文件 makefile放入源程序目录,其内容总是# DO NOT EDIT THIS FILE. Edit .sources. if you want to add a new source# file to this component. This file merely indirects to the re al make file# that is shared by all the driver components of the Windows NT DDK#可编辑资料 - - - 欢迎下载精品名师归纳总结学习资料 名师精选 - - - - - - - - - -第 4 页,共 19 页 - - - - - - - - - -可编辑资料 - - - 欢迎下载精品名师归纳总结资料word 精心总结归纳 - - - - - - - - - - - -.INCLUDE $NTMAKEENVmakefile.def9. 把文件 Sources放入源程序目录,内容为TARGETNAME=RamDrive/这是要生成的驱动程序.sys文件的名字TARGETPATH=obj /.sys文件所在目录的上层目录,(由于ddk的 bug应手工在 obj目录下创建checked和 free目录,以作为 .sys的最终存放目录TARGETTYPE=DRIVER /驱动程序的类型,一般不变 INCLUDES=$BASEDIRinc /ddk包含文件路径,一般不变 SOURCES=RamDrive.cpp RamDrive.rc /源文件 不要头文件 ,资源文件 BROWSER_INFO = 1 /如想要浏览信息,就要有本行。否就可无10. 由于 MakeDrvr.bat在 DriverEnv目录,所以应把该目录添加到vc 的Executable files里面选 tools的 options菜单项,然后选directories页, 在show directories for一栏挑选 Executable files,然后添加即可至此,环境设置完毕,你可以按F7, build你的驱动程序了。2005年 9 月 24 日 15:20可编辑资料 - - - 欢迎下载精品名师归纳总结学习资料 名师精选 - - - - - - - - - -第 5 页,共 19 页 - - - - - - - - - -可编辑资料 - - - 欢迎下载精品名师归纳总结资料word 精心总结归纳 - - - - - - - - - - - -驱动程序开发 Hello Word!看了好多天的书!特殊到书店买了Windows 200/xp wdm设备驱动开发这本书,在这里我不想怎么评论它!对于高手来说,我觉得她肯定不能满意,但是对于像我这样想入门的人来说,似乎看了半天,仍是不知道从何下手。什么原理、模型、分层等等讲不讲,讲!肯定应当讲!但是你得快点告知我怎么先弄一个像“Hello Word.”的什么简洁来不能再简洁的完整的例子给我吖!到网上找阿找啊!那些高手啊!也不为我们新手写点图文并茂的上手资料。没方法!结合自己的需要再参考一些别人的东东,算是自己的一点不成熟的想法吧!我觉得下面这个介绍特别不错!我能看懂,所以贴了出来。我道为什么找不到“Hello Word.”了?原先在驱动开发的例子里是没有所谓的“Hello World”程序的。这主要仍是由于网络上的WDM资料太少造成的。但是程序的入口点 了? c 语言有 Main,用 Vc 的常观察的是WinMain, Delphi开发的是 Program里的 Begin ,但是驱动开发了?那也是应当有程序的入口点啊。后来我才明白了,那就是 DriverEntry函数。仍有一个问题让我怀疑了老半天,那就是驱动开发的源程序中需不需要 include头文件吖?为什么会怀疑了?那是由于我看了半天的书都没有看到一个完整的驱动程序结构。真的是郁闷。 下面是我看到的一个完整的结构,我先放上来,让大家看看驱动开发的结构吧。/*程序名称: Hello World for WDM文件名称: HelloWDM.cpp日期: 2002-8-16*/ 肯定要的头文件,声明白函数模块和变量:#include"HelloWDM.h"/*函数名称: DriverEntry功能描述: WDM程序入口(原先的WinMain被换成了 DriverEntry,也是驱动程序的大门)*/extern "C"是必需的,表示 “用 C 链接 ”。假如你的文件名是HelloWDM.c的话,这句可以省略。extern"C"NTSTATUS DriverEntryIN PDRIVER_OBJECT DriverObject, /IN是一个关键字表示这是一个输入参数, PDRIVER_OBJECT是一个数据结构的指针,就像PCHAR一样, 这个数据结构是什么样子的,后面我会列出来。她描述了一个驱动设备对象。可编辑资料 - - - 欢迎下载精品名师归纳总结学习资料 名师精选 - - - - - - - - - -第 6 页,共 19 页 - - - - - - - - - -可编辑资料 - - - 欢迎下载精品名师归纳总结资料word 精心总结归纳 - - - - - - - - - - - -IN PUNICODE_STRING RegistryPath/参数 RegistryPath指定了驱动程序注册表健的路径,由于驱动程序安装后总会在系统注册表里留下一点东西的。可编辑资料 - - - 欢迎下载精品名师归纳总结/ 指定 “添加设备 ”消息由函数 “ HelloWDMAddDevice来”处理:可编辑资料 - - - 欢迎下载精品名师归纳总结DriverObject-> DriverExtension-> AddDevice= HelloWDMAddDevice;可编辑资料 - - - 欢迎下载精品名师归纳总结/ 指定 “即插即用 ”消息由函数 “ HelloWDMPnp来”处理:可编辑资料 - - - 欢迎下载精品名师归纳总结DriverObject-> MajorFunction IRP_MJ_PNP =HelloWDMPnp;/ 返回一个 NTSTATUS值 STATUS_SUCCESS。几乎全部的驱动程序例程都必需返回一个 NTSTATUS值,这些值在NTSTATUS.H DDK头文件中有具体的定义。returnSTATUS_SUCCESS;/ NTSTATUS也是一个数据类型,上面我所说的消息有点不精确的,精确的说是“ I/O恳求包 ”,不过假如像我们以前懂得消息那样来懂得也无不行,我觉得两者太想了。无非就是上层的应用程序通过它来告知驱动程序,你要给我什么服务吧!IRP_MJ_PNP就是即插即用处理的恳求。你发没发觉上面其实是在制造进入各个房间的“小门 ”/*函数名称: HelloWDMAddDevice功能描述:处理“添加设备 ”消息*/NTSTATUS HelloWDMAddDevice IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT PhysicalDeviceObject/ 定义一个 NTSTATUS类型的返回值:NTSTATUS status;/ 定义一个功能设备对象(Functional Device Object):PDEVICE_OBJECT fdo;/ 创建我们的功能设备对象,并储存到fdo 中:status= IoCreateDeviceDriverObject,/ 驱动程序对象sizeof DEVICE_EXTENSION ,/ 要求的设备扩展的大小NULL,/ 设备名称,这里为NULL FILE_DEVICE_UNKNOWN,/ 设备的类型,在标准头文件WDM.H或NTDDK.H中列出的 FILE_DEVICE_xxx值之一0,/ 各种常量用OR 组合在一起,指示可删除介质、只读等。FALSE,/ 假如一次只有一个线程可以拜访该设备,为 TRUE ,否就为 FALSE可编辑资料 - - - 欢迎下载精品名师归纳总结学习资料 名师精选 - - - - - - - - - -第 7 页,共 19 页 - - - - - - - - - -可编辑资料 - - - 欢迎下载精品名师归纳总结资料word 精心总结归纳 - - - - - - - - - - - -& fdo ;/ 返回的设备对象/NT_SUCCESS宏用于测试IoCreateDevice内核是否胜利完成。不要遗忘检查对内核的全部调用是否胜利。NT_ERROR宏不等同于 .NT_SUCCESS,最好使 用.NT_SUCCESS,由于除了错误外,它仍截获警告信息。if . NT_SUCCESS status returnstatus;/ 创建一个设备扩展对象dx ,用于储备指向fdo 的指针:PDEVICE_EXTENSION dx= PDEVICE_EXTENSION fdo -> DeviceExtension; dx-> fdo=fdo ;/ 用 IoAttachDeviceToDeviceStack函数把 HelloWDM设备挂接到设备栈:dx-> NextStackDevice=IoAttachDeviceToDeviceStack fdo , PhysicalDeviceObject ;/ 设置 fdo 的 flags 。有两个 “位”是必需转变的,一个是必需清除DO_DEVICE_INITIALIZING标志,假如在DriverEntry例程中调用 IoCreateDevice,就不需要清除这个标志位。仍有一个是必需设置DO_BUFFER_IO 标志位:fdo-> Flags|=DO_BUFFERED_IO| DO_POWER_PAGABLE;fdo-> Flags&= DO_DEVICE_INITIALIZING;/ 返回值:returnSTATUS_SUCCESS;/*函数名称: HelloWDMPnp功能描述:处理“即插即用 ”消息*/NTSTATUS HelloWDMPnp IN PDEVICE_OBJECT fdo, IN PIRP Irp/ 创建一个设备扩展对象dx ,用于储备指向fdo 的指针:PDEVICE_EXTENSION dx= PDEVICE_EXTENSION fdo -> DeviceExtension;/ 第一要通过函数IoGetCurrentIrpStackLocation得到当前的IRP ,并由此得到 Minor Function:PIO_STACK_LOCATION IrpStack= IoGetCurrentIrpStackLocation Irp ;可编辑资料 - - - 欢迎下载精品名师归纳总结学习资料 名师精选 - - - - - - - - - -第 8 页,共 19 页 - - - - - - - - - -可编辑资料 - - - 欢迎下载精品名师归纳总结资料word 精心总结归纳 - - - - - - - - - - - -ULONG MinorFunction= IrpStack-> MinorFunction;/ 然后把这个 Minor Function传递给下一个设备栈:IoSkipCurrentIrpStackLocation Irp ;NTSTATUS status= IoCallDriver dx -> NextStackDevice, Irp ;/ 处理 “即插即用 ”次功能代码:/ 当 Minor Function等于 IRP_MN_REMOVE_DEVICE时,说明有设备被拔出或卸下,这时要取消资源安排并删除设备:if MinorFunction=IRP_MN_REMOVE_DEVICE/ 取消设备接口:IoSetDeviceInterfaceState & dx -> ifSymLinkName,FALSE ;RtlFreeUnicodeString & dx -> ifSymLinkName ;/ 调用 IoDetachDevice把 fdo 从设备栈中脱开:if dx -> NextStackDeviceIoDetachDevice dx -> NextStackDevice ;/ 删 除 fdo :IoDeleteDevice fdo ;/ 返回值:returnstatus;/*程序名称: Hello World for WDM文件名称: HelloWDM.h作者:罗聪日期: 2002-8-16*/ 头文件,只是声明一些函数和变量,比较简洁就不多说了,请读者自行讨论:#ifdef cplusplus extern"C"#endif可编辑资料 - - - 欢迎下载精品名师归纳总结学习资料 名师精选 - - - - - - - - - -第 9 页,共 19 页 - - - - - - - - - -可编辑资料 - - - 欢迎下载精品名师归纳总结资料word 精心总结归纳 - - - - - - - - - - - -#include"ntddk.h"#ifdef cplusplus#endiftypedefstruct_DEVICE_EXTENSIONPDEVICE_OBJECTfdo;PDEVICE_OBJECTNextStackDevice;UNICODE_STRINGifSymLinkName;DEVICE_EXTENSION, * PDEVICE_EXTENSION;NTSTATUS HelloWDMAddDevice IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT PhysicalDeviceObject ;NTSTATUS HelloWDMPnp IN PDEVICE_OBJECT fdo, IN PIRP Irp ;好了,第一个WDM版的 “Hello World”就介绍到这里,虽然实际上它什么都没有做,但是由于它包含了完整的框架,所以对于向我这样的新手来说仍是很有参考价值的。至于怎么编译及安装只有下次再说了2005年 9 月 25 日 15:32可编辑资料 - - - 欢迎下载精品名师归纳总结学习资料 名师精选 - - - - - - - - - -第 10 页,共 19 页 - - - - - - - - - -可编辑资料 - - - 欢迎下载精品名师归纳总结资料word 精心总结归纳 - - - - - - - - - - - -驱动程序开发 编译前传好啦,辛辛苦苦最终写完了程序,让我们编译运行吧!按下Ctrl+F5(嘿嘿,让我们先假设你习惯用VC 来写程序),我等啊等疑?怎么毫无动静的?再看看Output窗口,哇!有几百个错误啊!不禁头大 这是怎么回事了?原先, WDM 程序编译出来的并不是我们常见的.exe ,而是 .sys文件,在未经设置编译环境之前,是不能直接用VC 来编译的(这就是为什么会有几百个错误了)。这种类型 的文件你可以在WINNTSystem32Drivers里面找到许多。其实驱动程序也是一种PE 文件,它同样由DOS MZ header开头,也有完整的DOS stub和 PE header,同样拥有 Import table和 Export table那跟一般的 PE 文件有什么不一样了?那么就让我们先来做个小剖析,加深对.sys文件的熟悉吧第一祭出 Delphi里附带的 tdump.exe程序。让我们键入:C:WINNTSystem32Drivers>tdump ccport.sys -em -ee参数 -em是列出 Import table,-ee是列出 Export table。回车之后,屏幕列出一大堆东西:C:WINNTSYSTEM32DRIVERS>tdump ccport.sys -em -eeTurbo Dump Version 5.0.16.12 Copyright . 1988, 2000 Inprise Corporation Display of File CCPORT.SYSIMPORT:NTOSKRNL.EXE=hint:011Fh. memcpy IMPORT:NTOSKRNL.EXE=hint:003Dh. IoDeleteDeviceIMPORT:NTOSKRNL.EXE=hint:0030h. IoAttachDeviceToDeviceStackIMPORT:N