文章摘录自《Windows内核原理与实现》一书。
设备驱动程序是操纵设备的内核模块,I/O 管理器、即插即用管理器和电源管理器都需要与设备的驱动程序打交道。
在Windows I/O 系统中,设备驱动程序不仅为操作系统提供了支持各种 I/O 设备的能力, 也是 Windows 内核本身扩展的基础。Windows 可以动态地加载或卸载设备驱动程序,通过这些驱动程序来调整或扩展内核的功能。 Windows I/O 系统规定了设备驱动程序应遵循的接口, 这组接口是通用的,可适用于所有的内核模式驱动程序。设备驱动程序依据用途不同,可以分为以下三类:
1.即插即用驱动程序,也称为 WDM驱动程序。 它们通常为了驱动硬件设备而由硬件厂商提供,与 Windows的 I/O 管理器、即插即用管理器和电源管理器一起工作。Windows 自身携带了大量即插即用驱动程序,用于支持各种常见的存储设备、视频适配器、网络适配器以及输入设备等。
2.内核扩展驱动程序,也称为非即插即用驱动程序。它们扩展内核功能,或者提供了访问内核模式代码和数据的一种途径。它们并没有集成到即插即用管理器和电源管理器的管理框架中。早期的 Windows NT 驱动程序(在引入即插即用机制以前)都属于这一类类型,现在仍然有大量的内核扩展驱动程序。
3.文件系统驱动程序。它们接收针对文件的 I/O 请求,再进一步将这些请求转变成正真对于储存设备或网络设备的 I/O 请求,从而满足客户的原始请求。文件系统的驱动程序被放在对象管理器的\FileSystem 目录下,其他的驱动程序放在\Driver 目录下。
Windows 驱动程序模型 (WDM) 在 I/O 模型中增加了对即插即用、电源管理和 Windows 管理规范(WMI)的支持。而且,遵从 WDM 的驱动程序在 Windows 平台(包括 Windows 98/Windows 2000 以后的所有版本) 上至少是源代码兼容的,甚至也可能是二进制兼容的。WDM驱动程序又进一步划分成以下三类:
1.总线驱动程序。顾名思义,总线驱动程序管理一个总线设备,它负责检测总线上附载的所有设备,并通知即插即用管理器关于这些设备情况。总线驱动程序也负责总线的电源管理。
2.功能驱动程序。功能驱动程序管理具体的设备,在一个设备的设备栈中,功能驱动程序创建的设备对象(即 FDO)相当于操作系统控制该设备的逻辑接口。功能驱动程序是实际管理该设备的功能模块。
3.过滤驱动程序。在设备栈中,过滤驱动程序位于功能驱动程序之上或之下,它的用途是:监视一个设备的 I/O 请求以及这些请求的处理情况,或者,增加或改变一个设备或另一个驱动程序的行为。例如,病毒扫描工具常常利用过滤驱动来监视被读写的文件数据。
在WDM中,总线式可供其他设备附载的设备,其中既有像 PCI 和 SCSI 这样的物理总线设备,也有像 HAL这样的虚拟总线设备。总线驱动程序负责检测总线上的设备,并且协助即插即用管理器列举这些设备,而且它也控制该总线的物理配置。相反地,功能驱动程序要简单得多,通常只是控制一个设备的硬件而已。
在即插即用管理器列举得到的设备树中,每个设备节点都包含一个设备栈,设备栈中的各个设备对象分别由对应的驱动程序创建和实现。图 6.12 显示了不同类型WDM驱动程序在设备栈中的角色,以及它们之间的关系。
每个设备对象都是由对应的驱动程序创建的,设备的 PDO 是由总线驱动程序创建的,而 FDO 是由功能驱动程序创建的。在PDO和FDO之间,紧挨着PDO,可以由零个或多个总线过滤设备对象,他们由相应的总线过滤驱动程序创建。在总线过滤设备对象和 FDO之间,可以有零个或多个下层过滤设备对象。而在 FDO 之上, 则可以有零个或多个上层过滤设备对象。这些下层或上层过滤设备对象分别由相应的下层或上层过滤驱动程序创建。WDM规定了这样的设备栈结构,即合理地让参与其中的每个驱动程序实现它所负责的那部分功能,也提供了足够的扩展性,允许过滤驱动程序在不同层次上监视或修正一个设备的工作方式。
对于一个具体的设备而言,FDO代表了它对操作系统的逻辑接口。功能驱动程序往往会创建一个代表相应 PDO 的设备接口(通过I/O 管理器函数 IoRegisterDeviceInterface),因而应用程序或内核其他部分可以通过此设备接口与该设备打交道。对于一些复杂而又通用的设备,例如磁盘设备和网络适配器等,功能驱动程序又被进一步分成多个独立的驱动程序,由它们联合起来管理该 FDO 的 I/O 请求。在这一层意义上, WDM 驱动程序对硬件的支持可以进一步划分为类驱动程序(class driver)和端口驱动程序 (port driver),以及小端口驱动程序(miniport driver).类驱动程序实现了某一种类型的设备的 I/O 处理。对于已经标准化的设备类型,比如磁盘、网络适配器等,提供一个类驱动程序可以为不同厂商生产的设备实现通用的服务。端口驱动程序实现了与某一类型 I/O 端口相关的 I/O 处理,它们并不遵从驱动程的接口请求,而只是一些内核模式的辅助例程。小端口驱动程序则实现了驱动某一特定设备而需要的 I/O 服务。类驱动程序和小端口驱动程序的分工可以看成是针对一个或一类设备的 "通用" 和 "特殊" 的功能部分。类驱动程序实现的是 "通用" 或 "公共" 的 I/O 服务,而小端口驱动程序实现的是针对某一特定设备的 “特殊” 功能部分。