它也在它的驱动程序对象内的 Driverextension中,设置它的 AddDevice例程的入口点 如下: DriverObject->DriverExtension->AddDevice=DDAddDevice: 驱动程序能定义若干 Dispatch入口点,但是它只能在其驱动程序对象中定义一个 Startle 入口点、一个 AddDevice入口点,和一个 Unload入口点。 2.4.3其他标准驱动程序例程 如图2.5所示,与它们在各自驱动程序对象中为其设置入口点的那些例程一起,内核模式 驱动程序还拥有其他的标准例程。大多数标准驱动程序例程及其使用的一些配置相关的对 象是由I/0管理器定义的。ISR、 SynchCritsection例程、以及图2.5中所示的名字包含 “ custom”的那些例程,是由 Windows nt内核定义的 大多数驱动程序使用每个设备对象的设备扩展,它们创建这些设备对象以保持有关它们的 Ⅰ/O操作的设备特定状态,并且存储一些指针,这些指针指向那些为了其他标准例程它们 必须分配的任何系统资源。例如,在图2.5中所显示的 DDCustomTimerDpc例程请求驱动程 序提供对内核定义的定时器和DPC对象的存储 如2.2节,“终端用户1/0请求和 Windows2000文件对象”中提到那样,针对在图2.5中 左边所示的最低层驱动程序的一组标准的驱动程序例程,必然不同于针对较高层的驱动程 序的。在图2.5中所示的一些例程是设备相关或者配置相关的请求。其他的是可选的:你 能选择实现这样一个例程,这取决于驱动程序的设备的性质或者配置、驱动程序的设计和 驱动程序在分层驱动程序的链中所处的位置 除了 Dispatch、 AddDevice、 Startle、和 Unload例程之外,系统定义的标准驱动程序例 程还包括 InterruptService (ISR) 能产生中断的物理设备的驱动程序必须拥有ISR。ISR必须根据中断停止设备。然后,它所 应该做的仅仅是保存状态,并且排队一个DPC,以在较低硬件优先级上完成中断驱动的I/0 操作,而不是在ISR执行的优先级上完成 Dpc ForIsr 拥有ISR的驱动程序也应该拥有DPC,要么是一个 DpcForlsr,要么是一个或者多个 CustomDpc例程,以完成中断驱动的I/0操作。 SynchCritSection 任何带有与它的ISR共享数据或设备寄存器的例程的驱动程序必须拥有一个或多个 SynchCritSection程序,以便以多处理器安全方式访问共享的数据或者寄存器。 驱动程序中的IRP可能为一个不确定的间隔保持排队状态(所以用户可以取消先前提交的 I/O请求),这样的驱动程序必须有一个或多个 Cancel例程让用户取消I/0请求。应该拥 有 Cancel例程的驱动程序的例子是键盘、鼠标、并口、串口、和声音设备驱动程序(或位 于它们之上的驱动程序),以及文件系统驱动程序 Controller Control 必须通过一个物理控制器使到一个简单设备的操作同步的最低层设备驱动程序,诸如 AT”盘控制器,可以拥有 Controllercontrol例程。WDM驱动程序不能有 ontroller Control例程 InCompletion
21 它也在它的驱动程序对象内的 DriverExtension 中,设置它的 AddDevice 例程的入口点, 如下: DriverObject->DriverExtension->AddDevice=DDAddDevice; 驱动程序能定义若干 Dispatch 入口点,但是它只能在其驱动程序对象中定义一个 StartIo 入口点、一个 AddDevice 入口点,和一个 Unload 入口点。 2.4.3 其他标准驱动程序例程 如图 2.5 所示,与它们在各自驱动程序对象中为其设置入口点的那些例程一起,内核模式 驱动程序还拥有其他的标准例程。大多数标准驱动程序例程及其使用的一些配置相关的对 象是由 I/O 管理器定义的。ISR、SynchCritSection 例程、以及图 2.5 中所示的名字包含 “custom”的那些例程,是由 Windows NT 内核定义的。 大多数驱动程序使用每个设备对象的设备扩展,它们创建这些设备对象以保持有关它们的 I/O 操作的设备特定状态,并且存储一些指针,这些指针指向那些为了其他标准例程它们 必须分配的任何系统资源。例如,在图 2.5 中所显示的 DDCustomTimerDpc 例程请求驱动程 序提供对内核定义的定时器和 DPC 对象的存储。 如 2.2 节,“终端用户 I/O 请求和 Windows 2000 文件对象”中提到那样,针对在图 2.5 中 左边所示的最低层驱动程序的一组标准的驱动程序例程,必然不同于针对较高层的驱动程 序的。在图 2.5 中所示的一些例程是设备相关或者配置相关的请求。其他的是可选的:你 能选择实现这样一个例程,这取决于驱动程序的设备的性质或者配置、驱动程序的设计和 驱动程序在分层驱动程序的链中所处的位置。 除了 Dispatch、AddDevice、StartIo、和 Unload 例程之外,系统定义的标准驱动程序例 程还包括: InterruptService(ISR) 能产生中断的物理设备的驱动程序必须拥有 ISR。ISR 必须根据中断停止设备。然后,它所 应该做的仅仅是保存状态,并且排队一个 DPC,以在较低硬件优先级上完成中断驱动的 I/O 操作,而不是在 ISR 执行的优先级上完成。 DpcForIsr 拥有 ISR 的驱动程序也应该拥有 DPC,要么是一个 DpcForIsr,要么是一个或者多个 CustomDpc 例程,以完成中断驱动的 I/O 操作。 SynchCritSection 任何带有与它的 ISR 共享数据或设备寄存器的例程的驱动程序必须拥有一个或多个 SynchCritSection 程序,以便以多处理器安全方式访问共享的数据或者寄存器。 Cancel 驱动程序中的 IRP 可能为一个不确定的间隔保持排队状态(所以用户可以取消先前提交的 I/O 请求),这样的驱动程序必须有一个或多个 Cancel 例程让用户取消 I/O 请求。应该拥 有 Cancel 例程的驱动程序的例子是键盘、鼠标、并口、串口、和声音设备驱动程序(或位 于它们之上的驱动程序),以及文件系统驱动程序。 ControllerControl 必须通过一个物理控制器使到一个简单设备的操作同步的最低层设备驱动程序,诸如 “AT”盘控制器,可以拥有 ControllerControl 例程。WDM 驱动程序不能有 ControllerControl 例程。 IoCompletion
在IRP特定基础上监控较低层驱动程序如何完成特定请求的较高层驱动程序可能拥有一个 或多个 InCompletion例程。分配IRP把请求发送到较低层驱动程序的较高层驱动程序必须 有 InCompletion程序。关于较高层驱动程序如何使用 InCompletion例程的描述,参见 IRP和驱动程序特定的I/0栈位置” lorimer 为了确定驱动程序设备操作是否有超时,或更新某种驱动程序定义的变量(诸如计数 器),或者出于某种原因需要被周期性地调用的驱动程序,可能拥有 LoRimer例程 loRimer例程实际上是一个与设备对象有关的DPC例程,I/0管理器每秒调用一次。对驱动 程序创建的每个设备对象,它可能有一个 loRimer例程 CustomTimerDpc 需要周期性地以精细的间隔(不是每秒一次)或者可变的间隔被调用的驱动程序可以拥有 一个 CustomTimerDpc例程,而非 loRimer例程。除了它的 loRimer例程之外,驱动程序也 能有一个或多个 CustomTimerDpc例程。 需要在较低的硬件优先级(IRQL)上延迟完成中断驱动的I/0操作的驱动程序可能有 CustomDpc例程。几乎没有最低层驱动程序拥有 CustomDpc而让它们的ISR排队,除非它 们的设备要求多于一个 DpcForIsr例程来完成一个不同组的中断驱动的I/0操作 注意,图2.5中所示的 CustomTimerDpc和 loRimer例程实际上是系统定义的 Cus tomDpc例 程在系统时钟中断发生之后执行。 Reinitialize 需要各阶段中初始化自己的任何驱动程序可能有 Reinitialize例程。 Reinitialize例程 在 Driver Entry例程已返回控制并且其他驱动程序已初始化了它们自己之后被调用 AdapterControl 使用系统DMA的任何设备的驱动程序可能有 AdapterControl例程,这个例程通过系统DMA 控制器在它的设备和系统物理内存之间完成传递操作。非SCSI总线控制器的设备的驱动程 序通常必须拥有 AdapterControl例程。作为选择,执行基于包的DMA(要么系统,要么总 线控制器)的驱动程序可能拥有 AdapterlistControl例程,使用系统提供分散/收集支 持。细节参见第3章。 出于惯例,除 DriverEntry之外的所有的标准例程的名称中被加入一个标识性的、驱动程 序或设备特定的前缀。作为例子,本文使用“D”,如图2.5所示。遵循这个惯例,可以 使调试和维护驱动程序变得更容易。 244标准驱动程序例程的注意事项 当设计内核模式驱动程序时,注意下列事项 所有的驱动程序必须有至少一个 Dispatch例程,并且必须在其驱动程序对象中为驱动 程序处理的每个 IRP MJ XXX定义发送入口点。驱动程序能拥有与它所能处理的 IRP MJ XXX功能同样数量的 Dispatch例程。 如果在系统运行时驱动程序能被替换,驱动程序必须有 Unload例程,并且在其驱动程 序对象中定义一个 Unload入口点。 Unload例程负责释放任何系统资源,诸如 Windows 2000对象或者驱动程序分配的内存,这些资源通常在驱动程序本身被从系统卸载之前 使用
22 在 IRP 特定基础上监控较低层驱动程序如何完成特定请求的较高层驱动程序可能拥有一个 或多个 IoCompletion 例程。分配 IRP 把请求发送到较低层驱动程序的较高层驱动程序必须 有 IoCompletion 程序。关于较高层驱动程序如何使用 IoCompletion 例程的描述,参见 “IRP 和驱动程序特定的 I/O 栈位置”。 IoTimer 为了确定驱动程序设备操作是否有超时,或更新某种驱动程序定义的变量(诸如计数 器),或者出于某种原因需要被周期性地调用的驱动程序,可能拥有 IoTimer 例程。 IoTimer 例程实际上是一个与设备对象有关的 DPC 例程,I/O 管理器每秒调用一次。对驱动 程序创建的每个设备对象,它可能有一个 IoTimer 例程。 CustomTimerDpc 需要周期性地以精细的间隔(不是每秒一次)或者可变的间隔被调用的驱动程序可以拥有 一个 CustomTimerDpc 例程,而非 IoTimer 例程。除了它的 IoTimer 例程之外,驱动程序也 能有一个或多个 CustomTimerDpc 例程。 CustomDpc 需要在较低的硬件优先级(IRQL)上延迟完成中断驱动的 I/O 操作的驱动程序可能有 CustomDpc 例程。几乎没有最低层驱动程序拥有 CustomDpc 而让它们的 ISR 排队,除非它 们的设备要求多于一个 DpcForIsr 例程来完成一个不同组的中断驱动的 I/O 操作。 注意,图 2.5 中所示的 CustomTimerDpc 和 IoTimer 例程实际上是系统定义的 CustomDpc 例 程在系统时钟中断发生之后执行。 Reinitialize 需要各阶段中初始化自己的任何驱动程序可能有 Reinitialize 例程。Reinitialize 例程 在 DriverEntry 例程已返回控制并且其他驱动程序已初始化了它们自己之后被调用。 AdapterControl 使用系统 DMA 的任何设备的驱动程序可能有 AdapterControl 例程,这个例程通过系统 DMA 控制器在它的设备和系统物理内存之间完成传递操作。非 SCSI 总线控制器的设备的驱动程 序通常必须拥有 AdapterContro1 例程。作为选择,执行基于包的 DMA(要么系统,要么总 线控制器)的驱动程序可能拥有 AdapterListControl 例程,使用系统提供分散/收集支 持。细节参见第 3 章。 出于惯例,除 DriverEntry 之外的所有的标准例程的名称中被加入一个标识性的、驱动程 序或设备特定的前缀。作为例子,本文使用“DD”,如图 2.5 所示。遵循这个惯例,可以 使调试和维护驱动程序变得更容易。 2.4.4 标准驱动程序例程的注意事项 当设计内核模式驱动程序时,注意下列事项: ▪ 所有的驱动程序必须有至少一个 Dispatch 例程,并且必须在其驱动程序对象中为驱动 程序处理的每个 IRP_MJ_XXX 定义发送入口点。驱动程序能拥有与它所能处理的 IRP_MJ_XXX 功能同样数量的 Dispatch 例程。 ▪ 如果在系统运行时驱动程序能被替换,驱动程序必须有 Unload 例程,并且在其驱动程 序对象中定义一个 Unload 入口点。Unload 例程负责释放任何系统资源,诸如 Windows 2000 对象或者驱动程序分配的内存,这些资源通常在驱动程序本身被从系统卸载之前 使用
所有的PnP驱动程序必须有 AddDevice例程,并且在驱动程序对象的驱动程序扩展中 定义其入口点。 AddDevice例程负责为驱动程序控制的每一个PnP设备创建和初始化 设备对象。 驱动程序可以有 Startle例程,并且能在其驱动程序对象中定义一个 Startle入口 点。没有 Startle例程的任何最低层驱动程序必须创建并且管理发送到其 Dispatch例 程的内部IRP队列,除非它能在它的 Dispatch例程中完成它得到的所有IRP。较高层 驱动程序可以有 Startle例程,但是很少这样做,这是因为较高层驱动程序通常把 IRP从它们的 Dispatch例程直接传递到低层驱动程序。 微端口驱动程序对于前面的要求是个例外。可以参见本DDK中的设备类型特定的文档 中关于微端口驱动程序的要求 驱动程序是否有任何其他种类的标准例程取决于其功能和那个驱动程序如何适应系统 (例如,它是否与系统提供的驱动程序互操作)。细节参见这个DDK中设备类型特定 的文档 也参见下列的文档: 第2.6节,“设备对象和分层的驱动程序”,阐述不同种类的设备驱动程序如何使用 设备对象描述物理、逻辑、和虚拟的设备 第3章阐述驱动程序能使用的系统定义的对象的详细信息 第4章是标准驱动程序例程的综述,第5章到第15章阐述例程特定的需求 第16章是关于驱动程序如何管理系统定义的硬件优先级,标准驱动程序例程在其上执 在线DK中的术语表,是与编写驱动程序有关的术语和缩写词 《即插即用、电源管理、和安装设计指南》和《 Windows2000驱动程序开发参考》卷 1,阐述了PnP的需求 2.5设备配置和分层驱动程序 对于大多数普通设备, Windows2000DDK提供一组全功能的系统驱动程序的样例集。当为 类似的设备开发新驱动程序时,单独的样例驱动程序可以被用作模型。然而,系统的驱动 程序有个附加的设计请求:要使开发新的设备驱动程序是容易的。因而,许多系统的驱动 程序具有分层结构,这样使得特定的驱动程序能被重用,以支持为类似的设备开发的新驱 动程序 在大多数情况下,DDK提供的可重用的驱动程序是WM驱动程序,它是支持PnP的,并且 能为系统提供的、设备特定的最低层(PnP总线)驱动程序提供处理硬件独立性的操作 在某些情况下,诸如并行端口和SCSI端口驱动程序,这些可重用的驱动程序为高层的、设 备类型特定的类驱动程序提供支持。注意,几乎所有系统的可重用驱动程序进行新中间层 驱动程序的开发,这些中间层驱动程序将被加入到现存的驱动程序链中,正如“IRP和驱 动程序特定的I0栈位置”中已经描述的那样。 一个新(或者替换)的驱动程序在设备的驱动程序链中适合位置,部分取决于一个给定的 Windows平台中设备的硬件配置,也部分取决于新驱动程序能从现存的系统驱动程序获得 多少支持
23 ▪ 所有的 PnP 驱动程序必须有 AddDevice 例程,并且在驱动程序对象的驱动程序扩展中 定义其入口点。AddDevice 例程负责为驱动程序控制的每一个 PnP 设备创建和初始化 设备对象。 ▪ 驱动程序可以有 StartIo 例程,并且能在其驱动程序对象中定义一个 Startlo 入口 点。没有 StartIo 例程的任何最低层驱动程序必须创建并且管理发送到其 Dispatch 例 程的内部 IRP 队列,除非它能在它的 Dispatch 例程中完成它得到的所有 IRP。较高层 驱动程序可以有 StartIo 例程,但是很少这样做,这是因为较高层驱动程序通常把 IRP 从它们的 Dispatch 例程直接传递到低层驱动程序。 ▪ 微端口驱动程序对于前面的要求是个例外。可以参见本 DDK 中的设备类型特定的文档 中关于微端口驱动程序的要求。 ▪ 驱动程序是否有任何其他种类的标准例程取决于其功能和那个驱动程序如何适应系统 (例如,它是否与系统提供的驱动程序互操作)。细节参见这个 DDK 中设备类型特定 的文档。 也参见下列的文档: ▪ 第 2.6 节,“设备对象和分层的驱动程序”,阐述不同种类的设备驱动程序如何使用 设备对象描述物理、逻辑、和虚拟的设备 ▪ 第 3 章阐述驱动程序能使用的系统定义的对象的详细信息 ▪ 第 4 章是标准驱动程序例程的综述,第 5 章到第 15 章阐述例程特定的需求 ▪ 第 16 章是关于驱动程序如何管理系统定义的硬件优先级,标准驱动程序例程在其上执 行 ▪ 在线 DDK 中的术语表,是与编写驱动程序有关的术语和缩写词 ▪ 《即插即用、电源管理、和安装设计指南》和《Windows 2000 驱动程序开发参考》卷 1,阐述了 PnP 的需求 2.5 设备配置和分层驱动程序 对于大多数普通设备,Windows 2000 DDK 提供一组全功能的系统驱动程序的样例集。当为 类似的设备开发新驱动程序时,单独的样例驱动程序可以被用作模型。然而,系统的驱动 程序有个附加的设计请求:要使开发新的设备驱动程序是容易的。因而,许多系统的驱动 程序具有分层结构,这样使得特定的驱动程序能被重用,以支持为类似的设备开发的新驱 动程序。 在大多数情况下,DDK 提供的可重用的驱动程序是 WDM 驱动程序,它是支持 PnP 的,并且 能为系统提供的、设备特定的最低层(PnP 总线)驱动程序提供处理硬件独立性的操作。 在某些情况下,诸如并行端口和 SCSI 端口驱动程序,这些可重用的驱动程序为高层的、设 备类型特定的类驱动程序提供支持。注意,几乎所有系统的可重用驱动程序进行新中间层 驱动程序的开发,这些中间层驱动程序将被加入到现存的驱动程序链中,正如“IRP 和驱 动程序特定的 I/O 栈位置”中已经描述的那样。 一个新(或者替换)的驱动程序在设备的驱动程序链中适合位置,部分取决于一个给定的 Windows 平台中设备的硬件配置,也部分取决于新驱动程序能从现存的系统驱动程序获得 多少支持
2.5.1样例设备和驱动程序配置 本节介绍硬件和驱动程序配置之间的关系,用键盘和鼠标设备作为例子。配置因设备不同 而不同。任何设备配置的完成信息,参看本DDK中的设备特定的文档。 图2.6描述了键盘和鼠标这两个设备的可能硬件配置: 它们都直接的连到系统总线的某个位置 它们都通过一个键盘和辅助设备控制器被连结 图2.7描述了为图2.6中设备上的I/O操作所提供的相应的分层驱动程序 图2.6键盘和鼠标硬件配置 图2.7键盘和鼠标驱动程序层 注意,无论硬件配置如何,键盘和鼠标设备能使用系统的键盘类和鼠标类驱动程序,以处 理硬件无关的操作。这些被称为类驱动程序是因为每个都为特定的一类设备提供系统要求 的、但却与硬件无关的支持 相应的端口驱动程序实现设备特定的支持,以在每个物理设备上完成要求的I/0操作。x86 平台的系统(i8042)的键盘和辅助设备端口驱动程序,为鼠标和键盘管理设备特定的操 作。在每个设备被分别连结的硬件配置中,如图2.6所示,每个系统类驱动程序能在分开 的设备特定的端口驱动程序之上被分层,或者每个设备的单独驱动程序能作为一个分开 的、单一的(最低层)驱动程序被实现。 新的中间层驱动程序,例如PnP过滤器驱动程序,能被添加到图2.7中的配置中。例如 被增加到上述的键盘类驱动程序的过滤器驱动程序,可以在键盘输入通过I/0服务到达要 求它的子系统前,以平台特定的习惯过滤这个键盘输入。这样的过滤器驱动程序象键盘类 驱动程序一样,必须识别相同的IRP和 IOCTL 2.5.2添加驱动程序的注意事项 设计内核模式驱动程序时,要注意下列事项 系统提供的SCSⅠ和视频端口驱动程序不能被替换。 替换最低层驱动程序必须实现被替换的驱动程序的冋样功能。例如,替换键盘或者鼠 标端口驱动程序必须使用系统定义它自己和它所重用的系统提供的类驱动程序之间的 接口,反之亦然 将要插入到任何系统提供的一对驱动程序之间的新中间层驱动程序,必须能与那些驱 动程序或操作。换句话说,这样的新驱动程序必须遵照“处理IRP的注意事项”和 “标准驱动程序的注意事项”这些节中提供的事项。 26设备对象和分层驱动程序 除了某些微端口驱动程序,所有的内核模式驱动程序创建至少一种设备对象。(系统提供 的端口或者类驱动程序按照它们自己的需求创建和管理所有必要的系统定义的对象。)
24 2.5.1 样例设备和驱动程序配置 本节介绍硬件和驱动程序配置之间的关系,用键盘和鼠标设备作为例子。配置因设备不同 而不同。任何设备配置的完成信息,参看本 DDK 中的设备特定的文档。 图 2.6 描述了键盘和鼠标这两个设备的可能硬件配置: ▪ 它们都直接的连到系统总线的某个位置 ▪ 它们都通过一个键盘和辅助设备控制器被连结 图 2.7 描述了为图 2.6 中设备上的 I/O 操作所提供的相应的分层驱动程序。 图 2.6 键盘和鼠标硬件配置 图 2.7 键盘和鼠标驱动程序层 注意,无论硬件配置如何,键盘和鼠标设备能使用系统的键盘类和鼠标类驱动程序,以处 理硬件无关的操作。这些被称为类驱动程序是因为每个都为特定的一类设备提供系统要求 的、但却与硬件无关的支持。 相应的端口驱动程序实现设备特定的支持,以在每个物理设备上完成要求的 I/O 操作。x86 平台的系统(i8042)的键盘和辅助设备端口驱动程序,为鼠标和键盘管理设备特定的操 作。在每个设备被分别连结的硬件配置中,如图 2.6 所示,每个系统类驱动程序能在分开 的设备特定的端口驱动程序之上被分层,或者每个设备的单独驱动程序能作为一个分开 的、单一的(最低层)驱动程序被实现。 新的中间层驱动程序,例如 PnP 过滤器驱动程序,能被添加到图 2.7 中的配置中。例如, 被增加到上述的键盘类驱动程序的过滤器驱动程序,可以在键盘输入通过 I/O 服务到达要 求它的子系统前,以平台特定的习惯过滤这个键盘输入。这样的过滤器驱动程序象键盘类 驱动程序一样,必须识别相同的 IRP 和 IOCTL。 2.5.2 添加驱动程序的注意事项 设计内核模式驱动程序时,要注意下列事项: ▪ 系统提供的 SCSI 和视频端口驱动程序不能被替换。 ▪ 替换最低层驱动程序必须实现被替换的驱动程序的同样功能。例如,替换键盘或者鼠 标端口驱动程序必须使用系统定义它自己和它所重用的系统提供的类驱动程序之间的 接口,反之亦然。 ▪ 将要插入到任何系统提供的一对驱动程序之间的新中间层驱动程序,必须能与那些驱 动程序或操作。换句话说,这样的新驱动程序必须遵照“处理 IRP 的注意事项”和 “标准驱动程序的注意事项”这些节中提供的事项。 2.6 设备对象和分层驱动程序 除了某些微端口驱动程序,所有的内核模式驱动程序创建至少一种设备对象。(系统提供 的端口或者类驱动程序按照它们自己的需求创建和管理所有必要的系统定义的对象。) 一
些驱动程序必须创建多个设备对象:无论分层驱动程序链中特定驱动程序处于哪一层,单 独的设备对象描述一个物理、逻辑、和/或虚拟的设备,驱动程序为这个设备处理I/O请 换句话说,图2.5中显示的驱动程序对象描述一个单独的驱动程序,这个驱动程序可以创 建多个设备对象。I/O管理器维护被每个驱动程序创建的设备对象的列表,并且在驱动程 序对象中存储指向这个列表的指针 当每个标准驱动程序例程被调用的时候,被传递IRP的例程也被传递一个指向目标设备的 指针。大多数驱动程序使用目标设备对象的设备扩展来维护必要的设备状态信息或者驱动 程序决定的有关它们当前正在处理的I/0请求的环境数据 因为大多数总线、功能、和过滤器驱动程序(最低层和中间层驱动程序)在一个专用的线 程环境中执行,设备扩展是每个驱动程序维护设备状态和这个驱动程序需求的所有其他设 备特定的数据的主要地方。例如,在图2.5中所示的任何实现 Cus tomTimerDpc或者 CustomDpc例程的驱动程序通常在设备扩展中为必需的内核定义的定时器和/或DPC对象提 供存储空间。 每个拥有ISR的驱动程序必须为指向一组内核定义的中断对象的指针提供存储空间,并且 大多数设备驱动程序将这个指针存储在设备扩展中。当每个驱动程序创建设备对象,它确 定设备扩展的大小,并且每个驱动程序定义它自己的设备扩展的内容和结构。 下一节通过说明这些对象和代表性硬件配置之间的对应关系来介绍设备对象。第3章较详 细地分别描述设备对象,连同适配器和控制器对象。它也覆盖了所有其他系统定义的驱动 程序可能或必须使用的对象,例如中断对象,这个对象是为那些产生中断的物理设备的最 低层驱动程序而创建的。更多关于特定驱动程序必须创建的设备对象的信息,参见DDK中 的设备类型特定文档。 2.6.1针对样本配置的设备对象 图2.8说明代表键盘和鼠标设备的设备对象,这些设备在图2.6中显示。在图2.7中所示 的键盘和鼠标驱动程序通过调用I/0支持例程( IoCreateDevice)来创建这些设备对象 图2.8键盘和鼠标设备对象 对于键盘和鼠标设备来说,它们各自的端口和类驱动程序分别创建设备对象。端口驱动程 序创建物理设备对象(PD0)以代表物理的端口。每个类驱动程序创建它自己的功能设备对 象(FD0)以代表键盘或者鼠标设备,作为I/0请求的目标 每个类驱动程序调用I/0支持例程得到指向相邻的较低层驱动程序的设备对象的指针,因 此类驱动程序能将自己链在端口驱动程序之上,并且每个类驱动程序能为代表其物理设备 的目标PD0,把I/0请求发送到端口驱动程序 增加到配置的可选的过滤器驱动程序,将创建过滤器设备对象( filter d0)。像类驱动程 序一样,一个可选的过滤器驱动程序能链自己到设备栈中它的相邻的较低层驱动程序,并 且为目标PD发送I/0请求到相邻的较低层驱动程序 如图2.7中所示,每个端口驱动程序是总线(最低层的)驱动程序,所以产生中断的设备 的所有端口驱动程序必须创建中断对象,并且注册ISR
25 些驱动程序必须创建多个设备对象:无论分层驱动程序链中特定驱动程序处于哪一层,单 独的设备对象描述一个物理、逻辑、和/或虚拟的设备,驱动程序为这个设备处理 I/O 请 求。 换句话说,图 2.5 中显示的驱动程序对象描述一个单独的驱动程序,这个驱动程序可以创 建多个设备对象。I/O 管理器维护被每个驱动程序创建的设备对象的列表,并且在驱动程 序对象中存储指向这个列表的指针。 当每个标准驱动程序例程被调用的时候,被传递 IRP 的例程也被传递一个指向目标设备的 指针。大多数驱动程序使用目标设备对象的设备扩展来维护必要的设备状态信息或者驱动 程序决定的有关它们当前正在处理的 I/O 请求的环境数据。 因为大多数总线、功能、和过滤器驱动程序(最低层和中间层驱动程序)在一个专用的线 程环境中执行,设备扩展是每个驱动程序维护设备状态和这个驱动程序需求的所有其他设 备特定的数据的主要地方。例如,在图 2.5 中所示的任何实现 CustomTimerDpc 或者 CustomDpc 例程的驱动程序通常在设备扩展中为必需的内核定义的定时器和/或 DPC 对象提 供存储空间。 每个拥有 ISR 的驱动程序必须为指向一组内核定义的中断对象的指针提供存储空间,并且 大多数设备驱动程序将这个指针存储在设备扩展中。当每个驱动程序创建设备对象,它确 定设备扩展的大小,并且每个驱动程序定义它自己的设备扩展的内容和结构。 下一节通过说明这些对象和代表性硬件配置之间的对应关系来介绍设备对象。第 3 章较详 细地分别描述设备对象,连同适配器和控制器对象。它也覆盖了所有其他系统定义的驱动 程序可能或必须使用的对象,例如中断对象,这个对象是为那些产生中断的物理设备的最 低层驱动程序而创建的。更多关于特定驱动程序必须创建的设备对象的信息,参见 DDK 中 的设备类型特定文档。 2.6.1 针对样本配置的设备对象 图 2.8 说明代表键盘和鼠标设备的设备对象,这些设备在图 2.6 中显示。在图 2.7 中所示 的键盘和鼠标驱动程序通过调用 I/O 支持例程(IoCreateDevice)来创建这些设备对象。 图 2.8 键盘和鼠标设备对象 对于键盘和鼠标设备来说,它们各自的端口和类驱动程序分别创建设备对象。端口驱动程 序创建物理设备对象(PDO)以代表物理的端口。每个类驱动程序创建它自己的功能设备对 象(FDO)以代表键盘或者鼠标设备,作为 I/O 请求的目标。 每个类驱动程序调用 I/O 支持例程得到指向相邻的较低层驱动程序的设备对象的指针,因 此类驱动程序能将自己链在端口驱动程序之上,并且每个类驱动程序能为代表其物理设备 的目标 PDO,把 I/O 请求发送到端口驱动程序。 增加到配置的可选的过滤器驱动程序,将创建过滤器设备对象(filter DO)。像类驱动程 序一样,一个可选的过滤器驱动程序能链自己到设备栈中它的相邻的较低层驱动程序,并 且为目标 PDO 发送 I/O 请求到相邻的较低层驱动程序。 如图 2.7 中所示,每个端口驱动程序是总线(最低层的)驱动程序,所以产生中断的设备 的所有端口驱动程序必须创建中断对象,并且注册 ISR