第三卷内核模式驱动程序设计指南 第一部分一般内核模式
1 第三卷 内核模式驱动程序设计指南 第一部分 一般内核模式
第一部分一般内核模式 第1章 Windows2000和WM驱动程序 第2章分层的I/0、IRP和I/0对象 第3章系统定义的对象和对驱动程序的支持 第4章驱动程序基本结构 第5章 Driver Entry和 Reinitialize例程 第6章 Dispatch例程 第7章 Startle和队列管理例程 第8章中断服务例程 第9章 DpcForIsr例程和 CustomDpc例程 第10章 SynchCritSection例程 第11章 Adapter Control和 Controllercontrol例程 第12章 Cancel例程 第13章 InCompletion例程 第14章 LoRimer和 CustomTimerDpc例程 第15章 Unload例程 第16章常见的驱动程序设计问题
2 第一部分 一般内核模式 第 1 章 Windows 2000 和 WDM 驱动程序 第 2 章 分层的 I/O、IRP 和 I/O 对象 第 3 章 系统定义的对象和对驱动程序的支持 第 4 章 驱动程序基本结构 第 5 章 DriverEntry 和 Reinitialize 例程 第 6 章 Dispatch 例程 第 7 章 StartIo 和队列管理例程 第 8 章 中断服务例程 第 9 章 DpcForIsr 例程和 CustomDpc 例程 第 10 章 SynchCritSection 例程 第 11 章 AdapterControl 和 ControllerControl 例程 第 12 章 Cancel 例程 第 13 章 IoCompletion 例程 第 14 章 IoTimer 和 CustomTimerDpc 例程 第 15 章 Unload 例程 第 16 章 常见的驱动程序设计问题
第1章 Windows2000和WM驱动程序 本章叙述了什么是 Windows2000内核模式驱动程序,介绍了一些重要的驱动程序名词,并 总结了内核模式驱动程序的设计目标,解释为了满足这些设计目标, Windows2000(和 WDM)的内核模式驱动程序如何不同于其他操作系统的驱动程序 本章内容组织如下: 1.1 Windows2000组件一览 1.2 Windows2000中的驱动程序种类 1.3 Windows2000和wDM驱动程序设计目标 1.3.1移植性 1.3.2可配置性 1.3.3永远抢占优先和永远中断 1.3.4多处理器安全 1.3.5基于对象 1.3.6带有可复用IRP的包驱动I/0 1.3.7支持异步I/0 关于 Windows nt/ Windows2000操作系统环境的更多细节,可以参看 David solomon的 《 Inside windows n》(微软出版社,1998) 1.1 Windows2000组件一览 图1.1显示了 Microsoft windows2000操作系统环境的主要组件。 图1.1 Windows2000组件一览 在 Windows2000操作系统环境中,一部分组件运行在用户模式下,其他的则运行在内核模 式下。文件系统、中间层和最低层驱动程序被显示在图的左下方,其中包含了内核模式 I/0管理器。 如图1.1所示, Windows2000操作系统包括了许多内核模式组件,它们被精心地定义为功 能相互独立的组件。对内核模式驱动程序设计者来说,最感兴趣的就是内核Ⅰ/O管理、即 插即用管理( Plug and Play manager)、电源管理( Power Manager)、硬件抽象层 ( Hardware Abstraction Layer,HAL)、配置管理( Configuration Manager)、存储管 理( Memory Manager)、运行支持( Executive Support)和过程结构( Proce Structure)组件。对另一些设计者来说,感兴趣的其他组件可能包括对象管理( Ob ject Manager)和安全引用监控器( Security Reference Monitor) 即插即用(PnP)管理和电源管理是 Windows2000中的新组件。他们仅仅支持 Windows 2000驱动程序和WM驱动程序。有关 Windows2000和wDM驱动程序使用这些 Microsoft 操作系统新特性的更详细资料,请参见《 Windows2000驱动程序开发参考》的第1卷《即 插即用、电源管理和安装设计指南》
3 第1章 Windows 2000 和 WDM 驱动程序 本章叙述了什么是 Windows 2000 内核模式驱动程序,介绍了一些重要的驱动程序名词,并 总结了内核模式驱动程序的设计目标,解释为了满足这些设计目标,Windows 2000(和 WDM)的内核模式驱动程序如何不同于其他操作系统的驱动程序。 本章内容组织如下: 1.1Windows 2000 组件一览 1.2Windows 2000 中的驱动程序种类 1.3Windows 2000 和 WDM 驱动程序设计目标 1.3.1 移植性 1.3.2 可配置性 1.3.3 永远抢占优先和永远中断 1.3.4 多处理器安全 1.3.5 基于对象 1.3.6 带有可复用 IRP 的包驱动 I/O 1.3.7 支持异步 I/O 关于 Windows NT/Windows 2000 操作系统环境的更多细节,可以参看 David Solomon 的 《Inside Windows NT》(微软出版社,1998)。 1.1 Windows 2000 组件一览 图 1.1 显示了 Microsoft Windows 2000 操作系统环境的主要组件。 图 1.1 Windows 2000 组件一览 在 Windows 2000 操作系统环境中,一部分组件运行在用户模式下,其他的则运行在内核模 式下。文件系统、中间层和最低层驱动程序被显示在图的左下方,其中包含了内核模式 I/O 管理器。 如图 1.1 所示,Windows 2000 操作系统包括了许多内核模式组件,它们被精心地定义为功 能相互独立的组件。对内核模式驱动程序设计者来说,最感兴趣的就是内核 I/O 管理、即 插即用管理(Plug and Play Manager)、电源管理(Power Manager)、硬件抽象层 (Hardware Abstraction Layer,HAL)、配置管理(Configuration Manager)、存储管 理(Memory Manager)、运行支持(Executive Support)和过程结构(Process Structure)组件。对另一些设计者来说,感兴趣的其他组件可能包括对象管理(Object Manager)和安全引用监控器(Security Reference Monitor)。 即插即用(PnP)管理和电源管理是 Windows 2000 中的新组件。他们仅仅支持 Windows 2000 驱动程序和 WDM 驱动程序。有关 Windows 2000 和 WDM 驱动程序使用这些 Microsoft 操作系统新特性的更详细资料,请参见《Windows 2000 驱动程序开发参考》的第 1 卷《即 插即用、电源管理和安装设计指南》
1.2 Windows2000中的驱动程序种类 在 Windows2000操作系统中,有两个基本的驱动程序种类: 用户模式驱动程序(例如Win32VDD,它是为MS-DOS应用程序开发的专用设备)或另 一个被保护的子系统的驱动程序 用户模式驱动程序是与子系统细节相关的,我们不在这里讨论。更多VD的细节,参 考在线DDK中的“ Virtual device drivers(虚拟设备驱动程序)”文档。 针对逻辑、虚拟或物理设备的内核模式驱动程序 这些驱动程序作为 Windows nt执行体部分来运行: Windows nt是基础的、基于微内 核的操作系统,它支持一个或更多的保护子系统 些 Windows2000内核驱动程序也是wDM驱动程序,它们符合 Windows驱动程序模型 (wDM)。所有的wM驱动程序是PnP驱动程序,并支持电源管理。WDM驱动程序对 Microsoft windows98和 Windows2000操作系统来说,是源代码兼容的(不是二进 制兼容的)。 在这里,术语“ Windows2000驱动程序”通常指代任何运行于 Windows2000操作系统之 上的内核模式驱动程序(是WDM或不是)。必要的时候,本书会特别指出哪些是WDM驱动 程序,哪些只是 Windows2000驱动程序。名词“早期驱动程序”指的是那些为 Windows NT以前版本写的驱动程序,它们是不支持PnP的。 像操作系统自己,内核模式驱动程序是依据仔细定义的需求功能集,作为单独的、模块化 的组件来实现的。 所有的 Windows2000内核模式驱动程序,包括WDM驱动程序,都包含一组系统定义的标准 驱动程序例程和一些依赖于个别设备需求的内部例程。 图1.2内核模式驱动程序类型 如图1.2所示,有三种基本类型的内核模式驱动程序。每一种都有稍微不同的结构和完全 不同的功能 1.最高层驱动程序,例如系统支持的FAT、NTFS和CDFS文件系统驱动程序(FSD)。最 高层驱动程序通常依赖于较低层的驱动程序支持。 虽然特定的文件系统驱动程序可能、或不可能从一个或多个中间层驱动程序获得支 持,但是每个文件系统驱动程序最终依赖一个或多个下层外围设备(可能是PnP硬件 总线)驱动程序的支持 2.中间层驱动程序,例如虚拟磁盘、镜像、或指定设备类型的类驱动程序。中间层驱动 程序也需要较低层驱动程序的支持。 PnP功能驱动程序是中间层驱动程序,它们在一个I/0总线上控制特定的外围设备, 这个I/0总线是由PnP硬件总线驱动程序来控制的。同样还有PnP过滤器驱动程序 ( Pnp filter driver),它们在驱动程序栈( driver stack)内将它们自己插入到 PP功能驱动程序中去,以支持任何特定的外围设备。PnP功能和过滤器驱动程序的子 集也是WDM功能和过滤器驱动程序。 任何系统支持的向外输出一个系统定义的WDM类/微类接口的类驱动程序,实际上是 个带有一个或多个链接的WM微类驱动程序(有时称为WDM微驱动程序)的中间层驱 动程序。每一对相互链接的WDM类/微类,提供与WDM功能驱动程序或WDM“软件”总 线驱动程序相同的功能 4
4 1.2 Windows 2000 中的驱动程序种类 在 Windows 2000 操作系统中,有两个基本的驱动程序种类: ▪ 用户模式驱动程序(例如 Win32 VDD,它是为 MS-DOS 应用程序开发的专用设备)或另 一个被保护的子系统的驱动程序 用户模式驱动程序是与子系统细节相关的,我们不在这里讨论。更多 VDD 的细节,参 考在线 DDK 中的“Virtual Device Drivers(虚拟设备驱动程序)”文档。 ▪ 针对逻辑、虚拟或物理设备的内核模式驱动程序 这些驱动程序作为 Windows NT 执行体部分来运行:Windows NT 是基础的、基于微内 核的操作系统,它支持一个或更多的保护子系统。 一些 Windows 2000 内核驱动程序也是 WDM 驱动程序,它们符合 Windows 驱动程序模型 (WDM)。所有的 WDM 驱动程序是 PnP 驱动程序,并支持电源管理。WDM 驱动程序对 Microsoft Windows 98 和 Windows 2000 操作系统来说,是源代码兼容的(不是二进 制兼容的)。 在这里,术语“Windows 2000 驱动程序”通常指代任何运行于 Windows 2000 操作系统之 上的内核模式驱动程序(是 WDM 或不是)。必要的时候,本书会特别指出哪些是 WDM 驱动 程序,哪些只是 Windows 2000 驱动程序。名词“早期驱动程序”指的是那些为 Windows NT 以前版本写的驱动程序,它们是不支持 PnP 的。 像操作系统自己,内核模式驱动程序是依据仔细定义的需求功能集,作为单独的、模块化 的组件来实现的。 所有的 Windows 2000 内核模式驱动程序,包括 WDM 驱动程序,都包含一组系统定义的标准 驱动程序例程和一些依赖于个别设备需求的内部例程。 图 1.2 内核模式驱动程序类型 如图 1.2 所示,有三种基本类型的内核模式驱动程序。每一种都有稍微不同的结构和完全 不同的功能: 1. 最高层驱动程序,例如系统支持的 FAT、NTFS 和 CDFS 文件系统驱动程序(FSD)。最 高层驱动程序通常依赖于较低层的驱动程序支持。 虽然特定的文件系统驱动程序可能、或不可能从一个或多个中间层驱动程序获得支 持,但是每个文件系统驱动程序最终依赖一个或多个下层外围设备(可能是 PnP 硬件 总线)驱动程序的支持。 2. 中间层驱动程序,例如虚拟磁盘、镜像、或指定设备类型的类驱动程序。中间层驱动 程序也需要较低层驱动程序的支持。 PnP 功能驱动程序是中间层驱动程序,它们在一个 I/O 总线上控制特定的外围设备, 这个 I/O 总线是由 PnP 硬件总线驱动程序来控制的。同样还有 PnP 过滤器驱动程序 (PnP filter driver),它们在驱动程序栈(driver stack)内将它们自己插入到 PnP 功能驱动程序中去,以支持任何特定的外围设备。PnP 功能和过滤器驱动程序的子 集也是 WDM 功能和过滤器驱动程序。 任何系统支持的向外输出一个系统定义的 WDM 类/微类接口的类驱动程序,实际上是一 个带有一个或多个链接的 WDM 微类驱动程序(有时称为 WDM 微驱动程序)的中间层驱 动程序。每一对相互链接的 WDM 类/微类,提供与 WDM 功能驱动程序或 WDM“软件”总 线驱动程序相同的功能
PP软件总线驱动程序表示一组子设备,较高层的类、功能和/或过滤器驱动程序能连 接它们自己到这些子设备上,PmP软件总线驱动程序也是中间层驱动程序。例如,控 制多功能适配器的驱动程序是一个PnP软件总线驱动程序,这样的多功能适配器是用 于不同的设备的一个便携集合。根据便携设备的特性和它的驱动程序使用的接口,这 样的驱动程序也可能是WDM软件总线驱动程序。它似乎使得较高层驱动程序成为一个 PnP/WDM总线驱动程序。对于操作系统来说,驱动程序是以PnP/WDM驱动程序的面目 出现的,它服务于它自己的适配器,将它自己插入底层PP硬件总线驱动程序之上的 驱动程序堆栈中 3.最低层驱动程序,例如PnP硬件总线驱动程序,它控制一个I/0总线,这个总线连了 些外围设备在上面。最低层驱动程序不依赖于较低层驱动程序,而是控制物理外围 设备,例如总线 早期的M设备驱动程序直接地控制物理外围设备,它们是最低层的驱动程序,同样的 驱动程序例如 SCSI HBA( Host Bus Adapter,宿主总线适配器)驱动程序 PnP硬件总线驱动程序是系统提供的,并且通常动态控制可配置的I/0总线。这个驱 动程序通过与即插即用管理协作,为所有连到它所控制的I/0总线上的子设备,配置 和重新配置系统硬件资源(例如设备存储的映射和IRQ)。对其Ⅰ/0总线来说,PnP硬 件总线驱动程序包含了一部分 Windows nt早期版本中由HAL组件提供的功能 Windows2000网络驱动程序也能被划分为上述的基本类型之一。例如,NT服务器或转向器 是一个特定的文件系统驱动程序;传输堆栈中的任何驱动程序都是中间层驱动程序:物理 网卡(有时称为网络接口控制器或NIC)驱动程序则是最低层设备驱动程序。当然 Windows2000为网络设备提供了明确的接口和支持,例如NDIS( Network device Interface Specification,网络设备接口规范)库在网络传输堆栈的下界提供了NC驱动 程序和中间层驱动程序。 本书为文件系统和网络驱动程序设计者提供了一些有用的综述和背景信息,对于内核模式 设备和中间层驱动程序,以及包括WM驱动程序的设计者来说,本书主要是一个设计指 南。网络中间层和设备驱动程序的设计者也应该参考在线DDK中的“ Network driver Design Guide”和“ Reference”。文件系统驱动程序设计者和最高层网络驱动程序设计者 应当参考IFS工具包。 13 Windows2000和WDM驱动程序的设计目标 内核模式驱动程序与很多 Windows2000的设计目标相符合,特别是系统I/0管理器部分。 这些设计目标包括: 平台之间的移植性 硬件和软件的可配置性 永远抢占优先和永远中断 多处理器平台上的多处理器安全 基于对象 带可重用I/0请求包(IRP)的包驱动I/0 异步I/0支持 后面的小节中将向所有的 Windows2000内核模式和WDM驱动程序设计者介绍这些系统设计 目标
5 PnP 软件总线驱动程序表示一组子设备,较高层的类、功能和/或过滤器驱动程序能连 接它们自己到这些子设备上,PnP 软件总线驱动程序也是中间层驱动程序。例如,控 制多功能适配器的驱动程序是一个 PnP 软件总线驱动程序,这样的多功能适配器是用 于不同的设备的一个便携集合。根据便携设备的特性和它的驱动程序使用的接口,这 样的驱动程序也可能是 WDM 软件总线驱动程序。它似乎使得较高层驱动程序成为一个 PnP/WDM 总线驱动程序。对于操作系统来说,驱动程序是以 PnP/WDM 驱动程序的面目 出现的,它服务于它自己的适配器,将它自己插入底层 PnP 硬件总线驱动程序之上的 驱动程序堆栈中。 3. 最低层驱动程序,例如 PnP 硬件总线驱动程序,它控制一个 I/O 总线,这个总线连了 一些外围设备在上面。最低层驱动程序不依赖于较低层驱动程序,而是控制物理外围 设备,例如总线。 早期的 NT 设备驱动程序直接地控制物理外围设备,它们是最低层的驱动程序,同样的 驱动程序例如 SCSI HBA(Host Bus Adapter,宿主总线适配器)驱动程序。 PnP 硬件总线驱动程序是系统提供的,并且通常动态控制可配置的 I/O 总线。这个驱 动程序通过与即插即用管理协作,为所有连到它所控制的 I/O 总线上的子设备,配置 和重新配置系统硬件资源(例如设备存储的映射和 IRQ)。对其 I/O 总线来说,PnP 硬 件总线驱动程序包含了一部分 Windows NT 早期版本中由 HAL 组件提供的功能。 Windows 2000 网络驱动程序也能被划分为上述的基本类型之一。例如,NT 服务器或转向器 是一个特定的文件系统驱动程序;传输堆栈中的任何驱动程序都是中间层驱动程序;物理 网卡(有时称为网络接口控制器或 NIC)驱动程序则是最低层设备驱动程序。当然, Windows 2000 为网络设备提供了明确的接口和支持,例如 NDIS(Network Device Interface Specification,网络设备接口规范)库在网络传输堆栈的下界提供了 NIC 驱动 程序和中间层驱动程序。 本书为文件系统和网络驱动程序设计者提供了一些有用的综述和背景信息,对于内核模式 设备和中间层驱动程序,以及包括 WDM 驱动程序的设计者来说,本书主要是一个设计指 南。网络中间层和设备驱动程序的设计者也应该参考在线 DDK 中的“Network Driver Design Guide”和“Reference”。文件系统驱动程序设计者和最高层网络驱动程序设计者 应当参考 IFS 工具包。 1.3 Windows 2000 和 WDM 驱动程序的设计目标 内核模式驱动程序与很多 Windows 2000 的设计目标相符合,特别是系统 I/O 管理器部分。 这些设计目标包括: ▪ 平台之间的移植性 ▪ 硬件和软件的可配置性 ▪ 永远抢占优先和永远中断 ▪ 多处理器平台上的多处理器安全 ▪ 基于对象 ▪ 带可重用 I/O 请求包(IRP)的包驱动 I/O ▪ 异步 I/O 支持 后面的小节中将向所有的 Windows 2000 内核模式和 WDM 驱动程序设计者介绍这些系统设计 目标
1.3.1移植性 Windows2000输出两个系统提供的运行时库,它们包含了以Rtl为前缀的函数。内核模式 驱动程序可以使用相同的内核模式Rt1Xx例程作为执行组件,但是不能调用用户模式 TxxX例程。 每个NT执行组件输出一组内核模式支持的例程,驱动程序和所有其他的内核模式组件可以 调用这些例程。如果支持例程的底层实现随着时间的推移发生了变化,它的调用者依然可 以保持不变,因为定义组件的接口没有发生变化。 大多数 Windows2000组件完全是用C写成的,仅仅少部分的HAL和内核是用汇编语言写成 的。所以操作系统对于硬件平台来说是容易移植的。内核模式驱动程序应该也使用C来 写,从而使得它能被系统兼容的C编译器重新编译、链接,并且运行在不同的 Windows 2000平台上。如果是一个wDM驱动程序,不用重新书写驱动程序部分的代码,也不用替换 驱动程序中的模块,就可以在 Windows98平台上运行 如果相同的特性不能保证被其他系统兼容的编译器所支持,驱动程序则不应该依赖于任何 特定系统兼容的C编译器或C支持库的特性。通常,驱动程序代码应该符合 ANSI C标准 要避免使用任何这个标准中描述为“实现定义的”的部分 特别地,编写可移植的 Windows2000驱动程序,最好避免以下的情况: 对数据类型的依赖,因为它可能随着平台的不同而在大小和表现形式上有所不同 调用任何保持状态的标准C运行时库函数 调用任何标准C运行时库函数,而操作系统已经提供了一个可以替换被调用函数的支 持例程 K提供了一组包含文件,这些文件中定义了系统特定的数据类型和常数,驱动程序(以 及所有其他内核模式组件)可以使用它们来保证平台之间的可移植性。大多数驱动程序包 含了主DDK内核模式的包含文件之一,这些文件是: ntddk.h和wdm.h。这些主包含文件不 仅收录了系统提供的头文件,它们定义了基本的内核模式类型;而且,还收录了针对不同 处理器构架特定的头文件的合适选择,从而驱动程序能被使用相应的编译器指令编译。 对于WDM驱动程序,DK提供了一组包含文件,它们输出 Windows2000内核模式支持例 程、宏、常数以及类型的一个子集。WDM驱动程序使用主DDK包含文件wdm.h而不是 ntddk.h。包含wdm.h以及只使用它所输出的支持例程、宏、常数以及类型,使得WDM驱动 程序可以象在 Windows2000上一样在 Windows98上编译运行 如果驱动程序需要与平台有关的定义,最好是将这些定义用# ifdef语句单独分割开,这样 就能使驱动程序针对合适的硬件平台被编译和连接。当然,使用DK主头文件提供的支持 例程、宏、常数和类型,你几乎可以避免实现任何与平台有关的条件编译代码 某些驱动程序包含系统提供的其他头文件来确保 Windows平台上的可移植性,特别是 SCSI、NIS、以及视频微端口驱动程序。关于这些类型的驱动程序的头文件的详细信息分 别参看第3部分,“存储驱动程序”;以及在线DDK中的“ Graphics Driver Desi Guide(图形驱动程序设计指南)”和“ Reference(参考)”,“ Network Driver guide (网络驱动程序设计指南)”和“ Reference(参考)” 1.3.2可配置性 因为 Windows nt/ Windows2000是一个可移植的操作系统,所以,设备及其驱动程序必须 是硬件可配置和软件可配置的
6 1.3.1 移植性 Windows 2000 输出两个系统提供的运行时库,它们包含了以 Rtl 为前缀的函数。内核模式 驱动程序可以使用相同的内核模式 RtlXxx 例程作为执行组件,但是不能调用用户模式 RtlXxx 例程。 每个 NT 执行组件输出一组内核模式支持的例程,驱动程序和所有其他的内核模式组件可以 调用这些例程。如果支持例程的底层实现随着时间的推移发生了变化,它的调用者依然可 以保持不变,因为定义组件的接口没有发生变化。 大多数 Windows 2000 组件完全是用 C 写成的,仅仅少部分的 HAL 和内核是用汇编语言写成 的。所以操作系统对于硬件平台来说是容易移植的。内核模式驱动程序应该也使用 C 来 写,从而使得它能被系统兼容的 C 编译器重新编译、链接,并且运行在不同的 Windows 2000 平台上。如果是一个 WDM 驱动程序,不用重新书写驱动程序部分的代码,也不用替换 驱动程序中的模块,就可以在 Windows 98 平台上运行。 如果相同的特性不能保证被其他系统兼容的编译器所支持,驱动程序则不应该依赖于任何 特定系统兼容的 C 编译器或 C 支持库的特性。通常,驱动程序代码应该符合 ANSI C 标准, 要避免使用任何这个标准中描述为“实现定义的”的部分。 特别地,编写可移植的 Windows 2000 驱动程序,最好避免以下的情况: ▪ 对数据类型的依赖,因为它可能随着平台的不同而在大小和表现形式上有所不同 ▪ 调用任何保持状态的标准 C 运行时库函数 ▪ 调用任何标准 C 运行时库函数,而操作系统已经提供了一个可以替换被调用函数的支 持例程 DDK 提供了一组包含文件,这些文件中定义了系统特定的数据类型和常数,驱动程序(以 及所有其他内核模式组件)可以使用它们来保证平台之间的可移植性。大多数驱动程序包 含了主 DDK 内核模式的包含文件之一,这些文件是:ntddk.h 和 wdm.h。这些主包含文件不 仅收录了系统提供的头文件,它们定义了基本的内核模式类型;而且,还收录了针对不同 处理器构架特定的头文件的合适选择,从而驱动程序能被使用相应的编译器指令编译。 对于 WDM 驱动程序,DDK 提供了一组包含文件,它们输出 Windows 2000 内核模式支持例 程、宏、常数以及类型的一个子集。WDM 驱动程序使用主 DDK 包含文件 wdm.h 而不是 ntddk.h。包含 wdm.h 以及只使用它所输出的支持例程、宏、常数以及类型,使得 WDM 驱动 程序可以象在 Windows 2000 上一样在 Windows 98 上编译运行。 如果驱动程序需要与平台有关的定义,最好是将这些定义用#ifdef 语句单独分割开,这样 就能使驱动程序针对合适的硬件平台被编译和连接。当然,使用 DDK 主头文件提供的支持 例程、宏、常数和类型,你几乎可以避免实现任何与平台有关的条件编译代码。 某些驱动程序包含系统提供的其他头文件来确保 Windows 平台上的可移植性,特别是, SCSI、NDIS、以及视频微端口驱动程序。关于这些类型的驱动程序的头文件的详细信息分 别参看第 3 部分,“存储驱动程序”;以及在线 DDK 中的“Graphics Driver Design Guide(图形驱动程序设计指南)”和“Reference(参考)”, “Network Driver Guide (网络驱动程序设计指南)”和“Reference(参考)”。 1.3.2 可配置性 因为 Windows NT/Windows 2000 是一个可移植的操作系统,所以,设备及其驱动程序必须 是硬件可配置和软件可配置的
例如,在一个热插拔的RAID(廉价磁盘冗余阵列)配置中,用户可以在运行的时候替换磁 盘。这样的设备被称为是硬件可配置的。它的驱动程序不能假定给定的磁盘设备会在某个 特定的位置固定。因此,为了保持可移植性,它的驱动程序一定不能包含硬编码的与机器 有关的值 这类磁盘设备的驱动程序可以在任何给定的机器上对一个或多个文件系统提供硬件级支 持,当然这取决于用户如何对这些磁盘分区。另外,中间层驱动程序能为高层文件系统驱 动程序提供灾难恢复(镜像分区、带集、和/或卷集)支持,这样的机器通常具有充足的存 储能力。换句话说,同样的物理磁盘驱动程序能为一些机器提供对多种高层驱动程序的支 持,而对其他的机器则不能。这样的磁盘驱动程序是软件可配置的,它们都是中间层和文 件系统驱动程序,并且它们最终依赖于底层设备和/或即插即用(PnP)硬件总线驱动程 序 Windows nt/2000HAL组件被实现成一个动态连接库,它负责所有的硬件层、平台特定支 持,包括内核模式驱动程序在内,系统中的其他任何组件都需要它的支持。HAL输出的例 程提供了平台硬件与包括所有驱动程序在内的系统软件组件之间的一个接口,这些例程隐 藏了平台特定的硬件细节,例如高速缓存、I/0总线、中断等等。 系统支持的PnP硬件总线驱动程序,在PnP管理器的合作下对HAL组件提供了类似的功 能。这就是说,PnP管理器与每一个PnP硬件总线驱动程序合作,提供特定类型I/0总线 的平台硬件和系统软件之间的接口 PnP管理器创建一个设备树,它的节点代表系统中所有的设备,包括总线和连在总线上的 设备。对于每一个设备,PnP管理器维护两个列表:一个是设备可以使用的硬件资源表, 另一个是设备实际占用的硬件资源表。设备驱动程序辅助PnP管理器创建这些列表,这些 列表被保存在注册表中。一旦在系统中增添或删除设备,PnP管理器有必要重新分配资 ,并更新列表 1.3.3永远抢占优先和永远中断 内核组件确定什么时候依照下列优先级调度标准之一来运行一段特定的代码: 针对线程的内核定义的运行时优先级 系统中每一个线程都被分配了一个优先级属性。通常,系统中的大多数线程拥有可变 的优先级属性:它们是总是抢占优先的,并且当前在同一优先级上的线程被轮询调 度。系统中的一些线程拥有实时优先属性:这些对时间要求苛刻的线程可以被拥有更 高实时优先级的线程抢占,直到它们释放控制 无论拥有什么优先级属性,系统中的任何线程在硬件和某种软件中断发生时被抢占 内核定义的中断请求级(IRL),在给定平台上被赋予特定的中断向量 内核也区分硬件和软件中断的优先次序,使得一些内核模式代码可以在更高的IRL上 运行。从而使得这些代码,包括大多数驱动程序,比系统中所有的线程拥有更高的优 先级。 一段内核模式代码在特定的IRQL上执行,这个IRQL定义了它的硬件优先级。内核模 式代码是总是可中断的:一个带有更高IRL值的中断可能在任何时候发生,从而导致 拥有更高IRL的另一段内核模式代码被处理器立即执行。换句话说,当一段代码在给 定的IRQL上运行时,内核屏蔽微处理器上所有小于等于当前IRQL值的中断向量。 通常,线程运行在 PASSIVW LEVEL IRQL上:没有中断向量被屏蔽。软件中断被赋予相对较 低的IRQL值( APC LEVEL、 DISPATCH LEVEL、或针对内核调试 WAKE LEVEL)。设备中断拥
7 例如,在一个热插拔的 RAID(廉价磁盘冗余阵列)配置中,用户可以在运行的时候替换磁 盘。这样的设备被称为是硬件可配置的。它的驱动程序不能假定给定的磁盘设备会在某个 特定的位置固定。因此,为了保持可移植性,它的驱动程序一定不能包含硬编码的与机器 有关的值。 这类磁盘设备的驱动程序可以在任何给定的机器上对一个或多个文件系统提供硬件级支 持,当然这取决于用户如何对这些磁盘分区。另外,中间层驱动程序能为高层文件系统驱 动程序提供灾难恢复(镜像分区、带集、和/或卷集)支持,这样的机器通常具有充足的存 储能力。换句话说,同样的物理磁盘驱动程序能为一些机器提供对多种高层驱动程序的支 持,而对其他的机器则不能。这样的磁盘驱动程序是软件可配置的,它们都是中间层和文 件系统驱动程序,并且它们最终依赖于底层设备和/或即插即用(PnP)硬件总线驱动程 序。 Windows NT/2000 HAL 组件被实现成一个动态连接库,它负责所有的硬件层、平台特定支 持,包括内核模式驱动程序在内,系统中的其他任何组件都需要它的支持。HAL 输出的例 程提供了平台硬件与包括所有驱动程序在内的系统软件组件之间的一个接口,这些例程隐 藏了平台特定的硬件细节,例如高速缓存、I/O 总线、中断等等。 系统支持的 PnP 硬件总线驱动程序,在 PnP 管理器的合作下对 HAL 组件提供了类似的功 能。这就是说,PnP 管理器与每一个 PnP 硬件总线驱动程序合作,提供特定类型 I/O 总线 的平台硬件和系统软件之间的接口。 PnP 管理器创建一个设备树,它的节点代表系统中所有的设备,包括总线和连在总线上的 设备。对于每一个设备,PnP 管理器维护两个列表:一个是设备可以使用的硬件资源表, 另一个是设备实际占用的硬件资源表。设备驱动程序辅助 PnP 管理器创建这些列表,这些 列表被保存在注册表中。一旦在系统中增添或删除设备,PnP 管理器有必要重新分配资 源,并更新列表。 1.3.3 永远抢占优先和永远中断 内核组件确定什么时候依照下列优先级调度标准之一来运行一段特定的代码: ▪ 针对线程的内核定义的运行时优先级 系统中每一个线程都被分配了一个优先级属性。通常,系统中的大多数线程拥有可变 的优先级属性:它们是总是抢占优先的,并且当前在同一优先级上的线程被轮询调 度。系统中的一些线程拥有实时优先属性:这些对时间要求苛刻的线程可以被拥有更 高实时优先级的线程抢占,直到它们释放控制。 无论拥有什么优先级属性,系统中的任何线程在硬件和某种软件中断发生时被抢占。 ▪ 内核定义的中断请求级(IRQL),在给定平台上被赋予特定的中断向量 内核也区分硬件和软件中断的优先次序,使得一些内核模式代码可以在更高的 IRQL 上 运行。从而使得这些代码,包括大多数驱动程序,比系统中所有的线程拥有更高的优 先级。 一段内核模式代码在特定的 IRQL 上执行,这个 IRQL 定义了它的硬件优先级。内核模 式代码是总是可中断的:一个带有更高 IRQL 值的中断可能在任何时候发生,从而导致 拥有更高 IRQL 的另一段内核模式代码被处理器立即执行。换句话说,当一段代码在给 定的 IRQL 上运行时,内核屏蔽微处理器上所有小于等于当前 IRQL 值的中断向量。 通常,线程运行在 PASSIVW_LEVEL IRQL 上:没有中断向量被屏蔽。软件中断被赋予相对较 低的 IRQL 值(APC_LEVEL、DISPATCH_LEVEL、或针对内核调试 WAKE_LEVEL)。设备中断拥
有较高的IRL值,内核则为系统关键的中断保留最高的IRQL值,例如系统时钟或总线错 误中断 一些系统支持例程运行在 IRQL PASSIVE LEVEL,原因有两个方面:一是因为一些内核模式 组件创建它们自己的线程,另一是因为一些支持例程被作为可分页代码实现,并且/或者访 问可分页数据。 同样的,某种标准驱动程序例程通常运行于 IRQL PASSIVE LEVEL。然而,几个标准的驱动 程序例程要么运行于 IRQL DISPATCH LEVEL,要么运行于设备IRQL(也称为 DIRQL),后 种是针对最低层的驱动程序来说的。参看《内核模式驱动程序设计指南》的第16章中的 “管理硬件优先级”,可以得到关于IRQL的细节。 通常,如果线程正在请求驱动程序的当前I/0操作,则在这些线程的环境中,仅仅最高层 的驱动程序被调用。如果线程已经请求了它的当前I/O操作,中间层或最低层驱动程序从 不假定它正在这些线程的环境中执行。 由于性能的原因(避免环境交换),几乎没有驱动程序创建它们自己的线程。因此,当 个标准的驱动程序例程被调用做某些工作时,驱动程序例程通常恰恰在当前线程环境中执 行。也就是说,它们在专用线程环境中执行。 任何内核模式例程都运行在比 PASSIVE LEVEL高的IRQL上,这些例程拥有比系统中所有线 程都高的优先级。驱动程序中的任何例程都是可中断的:运行在特定IRQL上的任何内核模 式例程一直保留处理器的控制权,除非例程运行时有更高的内核指定的IRQL发生。 甚至一个最底层的驱动程序中断服务例程(ISR)也能被其他运行在较高IRQL上的例程中 断(例如,被另一个驱动程序的ISR中断)。不像一些旧的PC操作系统中的驱动程序 Windows nt/ Windows2000驱动程序的ISR几乎不做任何驱动程序的I/0处理,因为驱动 程序的ISR一直到它返回,也不必保留它正在其上运行的CPU的控制。 相反,最低层的驱动程序必须在较低的IRQL上完成它的I/0操作的大部分,而不是它的 ISR的DIRL。为了获得好的系统整体性能,所有的运行在高级IRQL上的内核模式例程必 须迅速释放CPU的控制权。这样的例程不仅仅做它们在高级IRQL上必须作的,通常将一个 延迟过程调用(DPC)排队,以完成任何能在较低IRQL( DISPATCH LEVEL)上完成的操 作 操作系统的可中断、可抢占优先的设计目标是最大化平均性能。任何驱动程序的ISR能被 运行在较高IR哑L上的例程中断,并且任何线程都能被具有较高优先级的线程中断。虽然一 些线程拥有实时优先级属性,它们仍然能被具有更高优先级的线程抢占。然而 Windows NT/ Windows2000构架并没有提供一个真正的实时系统 如果想得到内核模式驱动程序中系统定义的标准例程的介绍,可以参看第2章,“分层的 I/0、IRP和1/O对象”。参看第4章,“基本驱动程序结构”可以得到这些例程的概述 1.34多处理器安全 在任何 Windows nt/ Windows2000多处理器平台中,需要满足下列条件 所有的CPU是相同的,并且它们要么都有协处理器,要么都没有。 所有的CPU共享内存,并且一致地访问内存。 在对称平台中,每一个CPU能访问内存、处理中断、访问I/0控制寄存器。(相对来 说,在不对称多处理器机器中,一个CPU可能为一组从属CPU处理所有中断。) Windows nt/ Windows2000被设计成一律运行在单一或对称多处理器平台上,内核模式的 Windows2000和WDM驱动程序应该被同样的设计
8 有较高的 IRQL 值,内核则为系统关键的中断保留最高的 IRQL 值,例如系统时钟或总线错 误中断。 一些系统支持例程运行在 IRQL_PASSIVE_LEVEL,原因有两个方面:一是因为一些内核模式 组件创建它们自己的线程,另一是因为一些支持例程被作为可分页代码实现,并且/或者访 问可分页数据。 同样的,某种标准驱动程序例程通常运行于 IRQL_PASSIVE_LEVEL。然而,几个标准的驱动 程序例程要么运行于 IRQL DISPATCH_LEVEL,要么运行于设备 IRQL(也称为 DIRQL),后 一种是针对最低层的驱动程序来说的。参看《内核模式驱动程序设计指南》的第 16 章中的 “管理硬件优先级”,可以得到关于 IRQL 的细节。 通常,如果线程正在请求驱动程序的当前 I/O 操作,则在这些线程的环境中,仅仅最高层 的驱动程序被调用。如果线程已经请求了它的当前 I/O 操作,中间层或最低层驱动程序从 不假定它正在这些线程的环境中执行。 由于性能的原因(避免环境交换),几乎没有驱动程序创建它们自己的线程。因此,当一 个标准的驱动程序例程被调用做某些工作时,驱动程序例程通常恰恰在当前线程环境中执 行。也就是说,它们在专用线程环境中执行。 任何内核模式例程都运行在比 PASSIVE_LEVEL 高的 IRQL 上,这些例程拥有比系统中所有线 程都高的优先级。驱动程序中的任何例程都是可中断的:运行在特定 IRQL 上的任何内核模 式例程一直保留处理器的控制权,除非例程运行时有更高的内核指定的 IRQL 发生。 甚至一个最底层的驱动程序中断服务例程(ISR)也能被其他运行在较高 IRQL 上的例程中 断(例如,被另一个驱动程序的 ISR 中断)。不像一些旧的 PC 操作系统中的驱动程序, Windows NT/Windows 2000 驱动程序的 ISR 几乎不做任何驱动程序的 I/O 处理,因为驱动 程序的 ISR 一直到它返回,也不必保留它正在其上运行的 CPU 的控制。 相反,最低层的驱动程序必须在较低的 IRQL 上完成它的 I/O 操作的大部分,而不是它的 ISR 的 DIRQL。为了获得好的系统整体性能,所有的运行在高级 IRQL 上的内核模式例程必 须迅速释放 CPU 的控制权。这样的例程不仅仅做它们在高级 IRQL 上必须作的,通常将一个 延迟过程调用(DPC)排队,以完成任何能在较低 IRQL(DISPATCH_LEVEL)上完成的操 作。 操作系统的可中断、可抢占优先的设计目标是最大化平均性能。任何驱动程序的 ISR 能被 运行在较高 IRQL 上的例程中断,并且任何线程都能被具有较高优先级的线程中断。虽然一 些线程拥有实时优先级属性,它们仍然能被具有更高优先级的线程抢占。然而 Windows NT/Windows 2000 构架并没有提供一个真正的实时系统。 如果想得到内核模式驱动程序中系统定义的标准例程的介绍,可以参看第 2 章,“分层的 I/O、IRP 和 I/O 对象”。参看第 4 章,“基本驱动程序结构”可以得到这些例程的概述。 1.3.4 多处理器安全 在任何 Windows NT/Windows 2000 多处理器平台中,需要满足下列条件: ▪ 所有的 CPU 是相同的,并且它们要么都有协处理器,要么都没有。 ▪ 所有的 CPU 共享内存,并且一致地访问内存。 ▪ 在对称平台中,每一个 CPU 能访问内存、处理中断、访问 I/O 控制寄存器。(相对来 说,在不对称多处理器机器中,一个 CPU 可能为一组从属 CPU 处理所有中断。) Windows NT/Windows 2000 被设计成一律运行在单一或对称多处理器平台上,内核模式的 Windows 2000 和 WDM 驱动程序应该被同样的设计
为了能在对称多处理器(SMP)平台上安全运行,任何操作系统都必须解决这样一个问题 即,怎样保证正在某个处理器上运行的代码,不会同时访问和修改运行在另一个处理器上 的代码正在访问和修改的数据。例如,正在一个处理器上处理设备中断的最低层驱动程序 的ISR排斥其他对临界的、驱动程序定义的数据(或设备寄存器)的访问,以防它的设备 同时在另一个处理器上中断 此外,在单一处理器的机器中被序列化的驱动程序I/0操作在SMP机器中能被同时执行。 这就是说,当一个处理输入I/0操作的驱动程序例程在一个处理器上被执行的时候,另 个与设备通讯的例程能同时在另一个处理器上被执行。不论是运行在单处理器机器上,还 是SP机器上,都要求包括wDM驱动程序在内的所有内核模式驱动程序能同步访问系统定 义的数据或系统提供给驱动程序例程共享的资源,并且在任何时候要同步对物理设备的访 问 MT内核组件输出了一个机制,被称为自旋锁( spin lock),对称多处理器平台中一个或 多个正在运行的例程同时访问时,它被用来保护共享数据(或设备寄存器)。内核对自旋 锁的应用使用了两个策略: 在任何时刻,一个且仅一个例程能拥有一个特定的自旋锁:仅仅自旋锁的拥有者才能 访问它所保护的数据。另一个例程必须取得自旋锁后,才能访问相同的数据,并且 除非自旋锁的当前拥有者主动释放了它,否则其他任何例程都不能得到它。 象硬件和软件中断向量一样,内核为系统中的每一个自旋锁制定一个相关的IRL值。 内核模式例程只有运行在自旋锁指定的IRL上时,才能到特定的自旋锁。 这些策略用来保护某个驱动程序例程被更高优先级的驱动程序例程所抢占,前者通常是在 较低的IRL上运行,但是现在却拥有某个自旋锁,后者则希望获取同样的自旋锁,这通常 会造成死锁。 分配给某个自旋锁的IRL通常是能获得这个自旋锁的最高层IRQL例程的IRQL。一个最低 层驱动程序的ISR频繁地与驱动程序的DPC例程共享一个状态区,后者靠调用驱动程序提 供的临界区例程来访问共享区域。在这个例子中,保护共享区域的自旋锁拥有与 DIRQL相 同的IRL,设备中断通常发生在DIRL。当临界区例程拥有自旋锁并且在 DIRQL上访问共 享区域,ISR不能在单处理器机器中运行,这是因为设备中断被屏蔽,正如前面提到的那 样。在一个对程多处理器机器中,当临界区例程拥有自旋锁并且在 DIRQL访问共享数据 时,ISR还不能获得自旋锁以保护共享数据。 通过等待内核的调度者对象之一,一组内核模式线程能同步访问共享数据或资源。这些调 度对象有:事件、互斥体、信号量、定时器、或另一个线程。然而,大多数驱动程序不创 建它们自己的线程,因为当它们避免线程环境交换的同时,获得了更好的性能。对时间要 求比较苛刻的内核模式支持例程和驱动程序无论何时运行在 IRQL DISPATCH LEVEL或 DIRQL,都必须使用内核的自旋锁,从而来同步对共享数据和资源的访问。 想要得到更详细的信息,可以参看第16章“使用自旋锁和管理硬件优先级”,第3章“内 核调度对象” 1.3.5基于对象 Windows nt/ Windows2000是基于对象的系统。在执行体中,各种各样的组件定义一个或 多个对象类型。每个组件输出仅内核模式具有的支持例程,当这些例程被调用时,它们操 纵它的对象类型的实例。没有组件被允许直接访问另一个组件的对象类型的任何实例。每 个组件要想使用其他的组件对象,必须调用输出的支持例程
9 为了能在对称多处理器(SMP)平台上安全运行,任何操作系统都必须解决这样一个问题: 即,怎样保证正在某个处理器上运行的代码,不会同时访问和修改运行在另一个处理器上 的代码正在访问和修改的数据。例如,正在一个处理器上处理设备中断的最低层驱动程序 的 ISR 排斥其他对临界的、驱动程序定义的数据(或设备寄存器)的访问,以防它的设备 同时在另一个处理器上中断。 此外,在单一处理器的机器中被序列化的驱动程序 I/O 操作在 SMP 机器中能被同时执行。 这就是说,当一个处理输入 I/O 操作的驱动程序例程在一个处理器上被执行的时候,另一 个与设备通讯的例程能同时在另一个处理器上被执行。不论是运行在单处理器机器上,还 是 SMP 机器上,都要求包括 WDM 驱动程序在内的所有内核模式驱动程序能同步访问系统定 义的数据或系统提供给驱动程序例程共享的资源,并且在任何时候要同步对物理设备的访 问。 NT 内核组件输出了一个机制,被称为自旋锁(spin lock),对称多处理器平台中一个或 多个正在运行的例程同时访问时,它被用来保护共享数据(或设备寄存器)。内核对自旋 锁的应用使用了两个策略: ▪ 在任何时刻,一个且仅一个例程能拥有一个特定的自旋锁;仅仅自旋锁的拥有者才能 访问它所保护的数据。另一个例程必须取得自旋锁后,才能访问相同的数据,并且, 除非自旋锁的当前拥有者主动释放了它,否则其他任何例程都不能得到它。 ▪ 象硬件和软件中断向量一样,内核为系统中的每一个自旋锁制定一个相关的 IRQL 值。 内核模式例程只有运行在自旋锁指定的 IRQL 上时,才能到特定的自旋锁。 这些策略用来保护某个驱动程序例程被更高优先级的驱动程序例程所抢占,前者通常是在 较低的 IRQL 上运行,但是现在却拥有某个自旋锁,后者则希望获取同样的自旋锁,这通常 会造成死锁。 分配给某个自旋锁的 IRQL 通常是能获得这个自旋锁的最高层 IRQL 例程的 IRQL。一个最低 层驱动程序的 ISR 频繁地与驱动程序的 DPC 例程共享一个状态区,后者靠调用驱动程序提 供的临界区例程来访问共享区域。在这个例子中,保护共享区域的自旋锁拥有与 DIRQL 相 同的 IRQL,设备中断通常发生在 DIRQL。当临界区例程拥有自旋锁并且在 DIRQL 上访问共 享区域,ISR 不能在单处理器机器中运行,这是因为设备中断被屏蔽,正如前面提到的那 样。在一个对程多处理器机器中,当临界区例程拥有自旋锁并且在 DIRQL 访问共享数据 时,ISR 还不能获得自旋锁以保护共享数据。 通过等待内核的调度者对象之一,一组内核模式线程能同步访问共享数据或资源。这些调 度对象有:事件、互斥体、信号量、定时器、或另一个线程。然而,大多数驱动程序不创 建它们自己的线程,因为当它们避免线程环境交换的同时,获得了更好的性能。对时间要 求比较苛刻的内核模式支持例程和驱动程序无论何时运行在 IRQL DISPATCH_LEVEL 或 DIRQL,都必须使用内核的自旋锁,从而来同步对共享数据和资源的访问。 想要得到更详细的信息,可以参看第 16 章“使用自旋锁和管理硬件优先级”,第 3 章“内 核调度对象”。 1.3.5 基于对象 Windows NT/Windows 2000 是基于对象的系统。在执行体中,各种各样的组件定义一个或 多个对象类型。每个组件输出仅内核模式具有的支持例程,当这些例程被调用时,它们操 纵它的对象类型的实例。没有组件被允许直接访问另一个组件的对象类型的任何实例。每 个组件要想使用其他的组件对象,必须调用输出的支持例程
对这些约定的严格遵守使得 Window Nt/ Windows2000具有移植性和伸缩性。例如,操作系 统将来的某个版本能包含一个完全或部分被重写的内核组件,这个组件定义了相同的对象 类型,但是可能使用了完全不同的内部结构,却可以输出一组具有与现存组件所输出的例 程相同名字和参数的支持例程。这个假定的被重写的内核版本将对现存系统中任何其他的 执行组件的移植性没有任何影响。换句话说,操作系统组件没有使用后门通讯,并且驱动 程序也必须避免这种使用,以保持系统的移植性和可配置性 与操作系统相似,驱动程序及其设备也是基于对象的。包括用户模式代码在内,对于系统 中所有其他的组件,对某个设备的连接被描述成I/0管理器的文件对象之一的打开操作 在I/0系统中,每一个驱动程序的逻辑、虚拟、和/或物理设备被描述为设备对象。在I/0 管理器中,每一个驱动程序的加载映像被描述成一个驱动程序对象。I/0管理器为文件对 象、设备对象和驱动程序对象定义对象类型 像任何其他的可执行组件,驱动程序通过调用内核模式支持例程来使用对象,这些支持例 程是由Ⅰ0管理器和其他系统组件输出的。内核模式支持例程通常拥有明确的名称,指明 了每次操纵的特定对象和在这个对象上执行的操作。这些支持例程名称的形式如下: PrefixOperationOb ject 这里 Preti 指明了输出支持例程的内核模式组件,并且还通常指明了定义对象类型的组件。大多数前 缀有两个字母 Operation 描述对这个对象作什么。 Object 指明对象类型 例如, IoCreateDevice,在设备初始化过程中每个内核模式驱动程序都要调用这个例程 次或多次,从名字可以看出,这个例程创建一个设备对象,以描述一个物理、逻辑、或虚 拟设备,作为I/0请求的目标。 为了方便起见,一个系统组件能输出调用其他组件的支持例程。特别是,I/0管理器输出 特定例程,以简化驱动程序开发。例如, IoConnectInterrupt是一个最低层的驱动程序调 用,被用来注册它们的中断服务例程(ISR),它调用针对中断的内核的支持例程 在线DDK中的术语表包括了一组系统对象的定义,它们对驱动程序开发者非常有用。关于 对最低层和中间层驱动程序特别有用的支持例程的详细信息,参见巛 Windows2000驱动程 序开发参考》的卷1和卷2,以及在线DDK 1.36带有可复用IRP的包驱动I/0 Ⅰ/O管理器的主要工作是接收I/0请求(通常来自用户模式应用程序)、创建IRP以描述 它们、发送IRP到合适的驱动程序、跟踪它们直到它们被完成,还有返回状态到每个1/0 操作的初始请求者。I/O管理器、即插即用管理器和电源管理器使用IRP与包括WM驱动 程序在内的内核模式驱动程序通信,并且允许驱动程序之间相互通讯 注意,一些IRP可以被发送到多个驱动程序。例如,一个在某个磁碟上打开文件的请求可 能首先到达文件系统驱动程序,通过中间层镜像驱动程序,最终到达磁盘驱动程序,可能 是一个PnP硬件总线驱动程序。 因此,每个IRP有一个固定的部分和一个或多个驱动程序特定的I/0栈位置( stack
10 对这些约定的严格遵守使得 Window NT/Windows 2000 具有移植性和伸缩性。例如,操作系 统将来的某个版本能包含一个完全或部分被重写的内核组件,这个组件定义了相同的对象 类型,但是可能使用了完全不同的内部结构,却可以输出一组具有与现存组件所输出的例 程相同名字和参数的支持例程。这个假定的被重写的内核版本将对现存系统中任何其他的 执行组件的移植性没有任何影响。换句话说,操作系统组件没有使用后门通讯,并且驱动 程序也必须避免这种使用,以保持系统的移植性和可配置性。 与操作系统相似,驱动程序及其设备也是基于对象的。包括用户模式代码在内,对于系统 中所有其他的组件,对某个设备的连接被描述成 I/O 管理器的文件对象之一的打开操作。 在 I/O 系统中,每一个驱动程序的逻辑、虚拟、和/或物理设备被描述为设备对象。在 I/O 管理器中,每一个驱动程序的加载映像被描述成一个驱动程序对象。I/O 管理器为文件对 象、设备对象和驱动程序对象定义对象类型。 像任何其他的可执行组件,驱动程序通过调用内核模式支持例程来使用对象,这些支持例 程是由 I/O 管理器和其他系统组件输出的。内核模式支持例程通常拥有明确的名称,指明 了每次操纵的特定对象和在这个对象上执行的操作。这些支持例程名称的形式如下: PrefixOperationObject 这里 Prefix 指明了输出支持例程的内核模式组件,并且还通常指明了定义对象类型的组件。大多数前 缀有两个字母。 Operation 描述对这个对象作什么。 Object 指明对象类型。 例如,IoCreateDevice,在设备初始化过程中每个内核模式驱动程序都要调用这个例程一 次或多次,从名字可以看出,这个例程创建一个设备对象,以描述一个物理、逻辑、或虚 拟设备,作为 I/O 请求的目标。 为了方便起见,一个系统组件能输出调用其他组件的支持例程。特别是,I/O 管理器输出 特定例程,以简化驱动程序开发。例如,IoConnectInterrupt 是一个最低层的驱动程序调 用,被用来注册它们的中断服务例程(ISR),它调用针对中断的内核的支持例程。 在线 DDK 中的术语表包括了一组系统对象的定义,它们对驱动程序开发者非常有用。关于 对最低层和中间层驱动程序特别有用的支持例程的详细信息,参见《Windows 2000 驱动程 序开发参考》的卷 1 和卷 2,以及在线 DDK。 1.3.6 带有可复用 IRP 的包驱动 I/O I/O 管理器的主要工作是接收 I/O 请求(通常来自用户模式应用程序)、创建 IRP 以描述 它们、发送 IRP 到合适的驱动程序、跟踪它们直到它们被完成,还有返回状态到每个 I/O 操作的初始请求者。I/O 管理器、即插即用管理器和电源管理器使用 IRP 与包括 WDM 驱动 程序在内的内核模式驱动程序通信,并且允许驱动程序之间相互通讯。 注意,一些 IRP 可以被发送到多个驱动程序。例如,一个在某个磁碟上打开文件的请求可 能首先到达文件系统驱动程序,通过中间层镜像驱动程序,最终到达磁盘驱动程序,可能 是一个 PnP 硬件总线驱动程序。 因此,每个 IRP 有一个固定的部分和一个或多个驱动程序特定的 I/O 栈位置(stack