WDM设备驱动程序开发平台2

来源:互联网 发布:机器视觉 算法 编辑:程序博客网 时间:2024/06/05 02:58
一个设备驱动程序的模块组成主要包括:初始化自己、创建和删除设备、处理Win32打开和关闭文件句柄的请求、处理Win32系统的I/O请求、对设备的串行化访问、访问硬件、调用其它驱动程序、取消I/O请求、超时I/O请求、处理一个PnP设备被加入或删除的情况、处理电源管理请求、调用Windows管理诊断WMI向系统管理员报告。

  其中,"初始化"模块必不可少,所有驱动程序都需要通过分发例程处理用户的I/O请求。而WDM风格的设备驱动程序需要有"即插即用(PnP)"模块以及安装标识的INF文件。在上述不同模块之间需要交互,其中的一些交互可以直接通过函数调用,而大量信息需要通过数据结构传递(比如在"设备对象"之类的数据结构中可以存储每个设备的信息)。

  分发例程指的是"创建"、"读"、"写"、"关闭"等处理程序,它可以执行对IRP的初始化处理,检查参数的合法性。在驱动程序编写中常遇到的非常棘手的所谓"同步问题",指的就是两个或更多的IRP分发例程往往要"同时"运行,它不仅在多处理器系统中会遇到,而且在单处理器系统中有时也很尖锐:比如单处理器系统上的一个分发例程在等待对低层驱动程序调用完成的同时,另一个IRP分发例程又被调用。处理这种冲突的机制主要有两种:一种是临界段例程,依此保证代码不会被中断处理程序中断;另一种机制是通过StartIo例程串行处理IRP,每个设备对象有一个内部的IRP队列,驱动程序的分发例程把IRP插入到这个设备队列中,内核I/O管理器从该队列一个个取出IRP,并传递到驱动程序的StartIo例程,StartIo例程串行处理IRP,以确保不与其它IRP处理程序冲突,但是StartIo例程仍然需要通过临界段例程避免与硬件中断发生冲突。

  中断是用于停止处理器对一个任务的执行,而被强制运行某个中断去处理代码。中断包括软件中断和硬件中断。中断具有优先级,低优先级中断会被高优先级的中断所中断,以保证重要任务会优先执行。硬件产生的中断总是比软件产生的中断优先级要高。硬件中断类型包括:设备中断请求级处理程序的执行、配置文件定时器、时钟、同步器、处理器之间中断级、电源故障级;软件中断包括异步过程调用执行、线程调度、延迟过程调用执行。至于常规线程执行则没有中断。

  驱动程序的主要的初始化入口点是一个称为DriverEntry的例程。多数WDM设备对象是由PnP管理器调用AddDevice入口点创建,该例程在插入新设备和安装INF文件指示相对应的驱动程序时被调用,之后,一系列PnP IRP被发送到驱动程序,指示设备应何时启动和查询其功能。为了让应用程序认知驱动设备存在,开发人员必须为每个设备对象创建使Win32可见的符号链接,这时可以有两种实现途径:一种是,采用显式的"硬编码"符号链接名,对此,应用程序的源代码中也具有设备名的硬编码;还有一种是采用设备接口,每个设备接口由一个GUID(全局唯一标识符)标识,对设备注册为具有某个特定的设备接口时就创建了一个符号链接。用户程序可以搜索有特定GUID的所有设备。驱动程序的代码是由系统内核通过发送I/O的IRP请求运行的。IRP是设备驱动程序的基本结构。

  内核所调用的驱动程序中的其它多个例程就是所谓回调例程(Callback),每个回调例程具有一个标准的函数原型,它适用于对应的环境。常用的回调例程包括:Unload(卸载驱动程序)、AddDevice(添加一个新的PnP设备)、StartIo(串行处理IRP)、ISR(中断服务例程)、DpcForIsr(延时过程调用例程)、临界段例程、撤消IRP的Cancel例程、一个低层驱动程序完成一个IRP处理时所调用的Completion例程、当DMA通道可用时调用的AdapterControl、Timer(秒级定时器回调例程)、低于1秒的超时例程CustomTimerDpc、用于处理工作队列的CustomDpc、Reinitialize(用于初始化耗时很长的驱动程序)。

  硬件驱动程序应当具有容错性,比如连接电缆断开或缓存区过载,并能够将错误信息反馈到应用程序。可以检查硬件状态位(如打印机缺纸指示),并能够处理快速I/O事件。

  与其它Windows编程类似的是,在编写硬件驱动程序时如何分配或访问内存是一件很讲究细节的技术活。我们知道,Windows中采用的虚拟内存意味着系统可以使用比物理内存更多的内存。虚拟内存的实现方式是:将每个应用程序的可能地址空间划分成固定大小的块,这些块称为页(x86处理器的页大小为4KB,Alpha处理器的页为8KB)。页可以驻留在物理内存,也可交换到硬盘。设备驱动程序分配的内存通常有两种:可以是交换型的分页内存,也可以是永久驻留的非分页内存。如果试图在线程调度或更高中断级访问分页内存,就会引起缺页故障,造成内核崩溃。即使是常规线程,如果访问非驻留的分页内存,内核就会造成线程阻塞,直到内存管理器把内存装回内存。问题的关键是,在设计驱动程序时,一方面忌讳滥用非分页内存,另一方面却不得不经常使用非分页内存。因为要在线程调度或更高中断级访问内存,必须调用非分页内存。当完成内存调用后,应当对所有类型的内存通过ExFreePool释放。假如不释放内存,将会减少内存,因为即使当驱动程序卸载后,内核并不收集这些分配了的内存。

  没有编写过硬件驱动程序的开发人员,在听到硬件驱动程序编程时,他们从直觉上会联想到需要与硬件资源打交道,包括I/O端口、中断、存储器地址和DMA(直接存储器访问)。其实,这是一种误解,因为有很多驱动程序不需要直接调用任何低层硬件资源,比如USB客户端驱动程序就不需要任何硬件资源,所有与硬件相关的琐细工作都有USB总线驱动程序完成,USB客户端驱动程序只是对总线驱动程序发出请求。
 
原创粉丝点击