Windows驱动程序的编写相对来说比较难一点,一般搞Windows 驱动都是专职人员来完成的。
1、 Windows驱动程序模型(WDM)
Windows环境下驱动程序共有三类,一类是VxD( Virtual Device Driver,虚拟设备驱动程序),起源于Windows 3.1 时代,用于Windows 95/98/Me操作系统中;一类是KMD( Kernel Mode Driver,内核模式驱动程序),用于Windows NT下;还有一类就是WDM(Win32 Driver Mode,Win32驱动程序模型),是微软从Windows 98开始,推出的一个新的驱动类型,它是一个跨平台的驱动程序模型,不仅如此WDM驱动程序还可以在不修改源代码的情况下经过重新编译后在非Intel平台上运行,毫不夸张地讲,WDM算得上是21世纪的驱动程序框架。
编写上位机驱动程序最常的方法是用WDM(Windows Driver Model, Windows 驱动程序模型)。WDM采用分层驱动程序模型,对于USB设备来说,可分为USB总线驱动程序(USBD)和USB功能驱动程序。USB总线驱动程序由操作系统提供,它位于USB功能驱动程序的下面,负责与实际的硬件打交道,实现烦琐的底层通信。USB功能驱动程序由设备开发者编写,位于USB总线驱动程序的上面,不与实际的硬件打交道,而是通过向USB总线驱动程序发送URB(USB Request Block,USB请求块)的IRP(I/O Request Packet,I/O请求包),来实现对USB设备信息的发送或接收。
2、开发WDM类型驱动程序的常方法
开发WDM驱动程序的方法三种,一种是利用微软提供的DDK驱动程序开发包,第二种是使用Compuware Numega公司的DriverStudio,第三种是使用KRF Tech公司的WinDriver。后两种给出驱动程序的框架,并对DDK中的一些操作进行封装,因此减少了开发时间,提高了效率。开发速度方面,第一种最慢,第三种最快。普及程度方法,第一种和第二种用得比较多。
对于DDK与DriverStudio的优缺点在网上争论了很久,我个人认为这种争论根本没有必要,因为它们之间的关系就好比MFC与SDK之间的关系一样。DriverStudio只是对DDK中的相关函数进行封装,让程序设计者只关注相关功能部分的实现,节省开发时间而已。不管使用什么工具,只要顺手,符合我们的习惯就行。
3、 USB驱动程序的结构
WDM体系结构实行分层处理,即设备驱动被分成了若干层,典型地分成:高层驱动程序、中间层驱动程序、底层驱动程序。每层驱动再把I/O请求划分成更简单的请求,以传给更下层的驱动执行。最底层的驱动程序在收到I/O请求后,通过硬件抽象层,与硬件发生作用,从而完成I/O请求工作。在这样的架构下,上面的驱动层就不需要对每个操作系统都要开发一遍了。
WDM还引入了功能设备对象FDO(Functional Device Object)与物理设备对象PDO(Physical Device Object)两个新类来描述硬件,一个PDO对应一个真实硬件。一个硬件只允许有一个PDO,但却可以拥有多个FDO,而在驱动程序中我们不是直接操作硬件而是操作相应的PDO与FDO。
USB驱动程序采用分层结构,位于上层的是USB设备驱动程序(或叫功能驱动程序Function Driver、用户驱动程序),负责创建FDO。总线驱动程序(Bus Driver)位于最底层,控制对总线上所有设备的访问,创建PDO代表发现的设备。
与传统PC总线(如PCI总线)设备的驱动程序相比,USB功能驱动程序从不直接与硬件对话。相反,它仅靠创建URB(USB请求块)并将URB提交到总线驱动程序就可完成硬件操作。在应用程序与WDM驱动程序通信方面,系统为每一个用户请求打包形成一个I/O请求包(IRP)结构,将其发送至驱动程序,并通过识别IRP中PDO来区别是发送给哪一个设备的。
NT驱动程序和一般的DOS/Windows C语言程序不一样,它没有main()或者WinMain()函数入口。和DLL类似地,它向操作系统显露一个名称为DriverEntry()的函数,在启动驱动程序的时候,操作系统将调用这个入口。DriverEntry除了做一些必要的设备初始化工作外,还初始化一些Dispatch例程入口。我们知道,NT应用和设备驱动程序打交道主要是通过CreateFile、 ReadFile、WriteFile 和DeviceIoControl等Win32 API来进行的。这些API其实都对应着驱动程序的一些Dispatch例程。而驱动程序除了DriverEntry以外,主要就是由这些Dispatch例程组成的。例如调用Win32 API CreateFile的时候,操作系统最终转化为对驱动程序IRP_MJ_CREATE功能代码所对应的 Dispatch例程的调用,如果驱动程序没有提供该例程, CreateFile调用就会失败。
NT中一些常用的功能代码和Win32 API的对象关系表
|
功能代码
|
说明
|
IRP_MJ_CREATE
|
打开设备CreateFile
|
IRP_MJ_CLEANUP
|
在关闭设备时,取消挂起的I/O请求CloseHandle
|
IRP_MJ_CLOSE
|
关闭设备CloseHandle
|
IRP_MJ_READ
|
从设备获得数据ReadFile
|
IRP_MJ_WRITE
|
向设备发送数据WriteFile
|
IRP_MJ_DEVICE_CONTROL
|
对用户模式或内核模式客户程序可用的控制操作DeviceIoControl
|
IRP_MJ_INTERNAL_DEVICE_CONTROL
|
只对内核模式客户程序可用的控制操作
|
IRP_MJ_QUERY_INFORMATION
|
得到文件的长度GetFileLength
|
IRP_MJ_SET_INFORMATION
|
设置文件的长度SetFileLength
|
IRP_MJ_FLUSH_BUFFERS
|
写输出缓冲区或丢弃输入缓冲区FlushFileBuffers、FlushConsoleInputBuffer、PurgeComm
|
IRP_MJ_SHUTDOWN
|
系统关闭InitialSystemShutdown
|
DDK有很多驱动程序的例子,其中有一个bulkusb的例子,仔细看过之后,其实把它修改一下就可以变成自己设备的驱动,这也正是Microsoft推荐驱动设计者开发设备驱动程序的方法。DDK确实过于博大精深,我想,能够达到自己的设备驱动可以正常工作这个目的就可以了,没有必要搞清楚驱动程序设计中的每一个细节。 如果使用DriverStudio工具进行开发,DriverStudio不仅提供相当数量的实例,还可以利用它的DriverWizard向导生成驱动程序框架,此框架已经完成大部分设备枚举工作,方便设计人员将精力集中在功能的实现上面。
4、 与设备驱动程序相关的文件
WDM类型的设备驱动程序扩展名为SYS,同时还应该包括一个INF类型的文件。INF文件含有安装一个WDM设备驱动程序需要的所有必要的信息,包括要复制的文件列表、要创建的注册表项、设备的旧和兼容ID等。INF文件是一个文本文件,它由节组成,每一节从节名称开始,后面是节内容。
当发现新的设备时(系统启动时,在安装热插拔设备时,或者从控制面板安装新设备时),就调用Windows的“添加新设备向导”执行这个向导扫描所有可用的INF文件,试图找到合适的驱动程序。Windows首先选择硬件ID匹配的设备的INF文件,否则它选择其兼容ID与设备ID最佳匹配的INF文件,若仍未找到提示用户选择驱动程序INF文件。然后根据INF文件的指令安装驱动程序,驱动程序可执行文件被复制到正确的位置,通常是indows\System32\Drivers目录,然后创建各种注册表项,驱动程序被装入内存,并执行它的DirverEntry例程,对新的设备调用AddDevice例程,给设备分配I/O、DMA、中断等资源(USB设备不需要分配资源),启动设备,然后正常的I/O操作就可以继续进行,使用后的INF文件复制到Windows INF子目录。
利用DriverStudio提供的DriverWizard向导生成驱动程序框后会自动生成这个INF文件,所以您也可以不必过多关心INF文件的细节。
注:以上部分内容摘自互联网