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