如何控制设备驱动程序的加载顺序
这篇文章中的信息适用于:
- 适用于 Windows NT 3.5 的 Microsoft Win32 设备驱动程序工具包
- 适用于 Windows NT 3.5 的 Microsoft Win32 设备驱动程序工具包
- 适用于 Windows NT 3.51 的 Microsoft Win32 设备驱动程序工具包
- 适用于 Windows NT 4.0 的 Microsoft Win32 设备驱动程序工具包
- 适用于 Windows 2000 的 Microsoft Win32 设备驱动程序工具包
本文的发布号曾为 CHS115486
概要
设计 Windows NT 时所采用的概念是:第一个提出占有某设备的驱动程序获得该设备的所有权。这个所有权可以共享,也可以独占,这由提出占有要求的设备驱动程序决定。如果设备驱动程序对设备提出了独占占有要求,则由以后加载的设备驱动程序对该设备尝试提出的任何占有要求都将失败。因此,设备驱动程序的加载顺序必须可以由设备驱动程序的作者进行修改。本文介绍可用于控制设备驱动程序加载顺序的两种方法。
更多信息
有两种方法可以用于控制设备驱动程序的加载顺序。这两种方法都利用了位于 \HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control 的注册表项。第一种方法是修改 ServiceGroupOrder。第二种方法是根据 GroupOrderList 分配用于决定驱动程序加载顺序的 Tag 值。Tag 值、起始值、类型值和组名称都位于 HKLM\SYSTEM\CurrentControlSet\Services\<drivername> 项中,必须先添加此项,然后这些值才能在组名称列表中列出。
这两种方法仅对起始值为 0 (SERVICE_BOOT_START) 或 1 (SERVICE_SYSTEM_START) 的设备驱动程序有效。在所有情况中,起始值为 0 的设备驱动程序都将在起始值为 1 的所有设备驱动程序尝试加载之前先加载。
方法 1:ServiceGroupOrder
ServiceGroupOrder 包含按加载顺序排列的组名称列表。下面原样列出 ServiceGroupOrder 的内容:
SCSI miniport
port
Primary disk
SCSI class
SCSI CDROM class
filter
boot file system
Base
Pointer Port
Keyboard Port
Pointer Class
Keyboard Class
Video Init
Video
Video Save
file system
Event log
Streams Drivers
NDIS
TDI
NetBIOSGroup
SpoolerGroup
根据 ServiceGroupOrder,“SCSI class”组中的设备驱动程序将在“Primary disk”组中的所有设备驱动程序之后,及“SCSI CDROM class”组中的设备驱动程序之前加载。设备驱动程序所在的组在列表中的位置越高,越先加载它。ServiceGroupOrder 列表将被扫描两次。首先加载所有起始值为 0 的设备驱动程序,然后加载所有起始值为 1 的设备驱动程序。因此,无论起始值为 0 的设备驱动程序在 ServiceGroupOrder 列表中处于什么位置,它都会在所有起始值为 1 的设备驱动程序之前加载。
设备驱动程序的作者可以编辑 ServiceGroupOrder。这样就可以在列表中的任意位置创建新组。名为“SAMPLDRV”的 SCSI class 设备驱动程序就是个很好的示例,因为“SCSIDISK”正在提出占有 SAMPLDRV 需要提出占有的设备,所以 SAMPLDRV 需要在 SCSIDISK 之前加载。下面是 SCSIDISK 的注册表项:
\registry\machine\system\currentcontrolset\services\scsidisk Type = REG_DWORD 0x00000001 Start = REG_DWORD 0x00000000 Group = SCSI class ErrorControl = REG_DWORD 0x00000000 DependOnGroup = REG_MULTI_SZ "SCSI miniport"
可以将名为“Load Me First”的新组添加到 ServiceGroupOrder 中,并将 SAMPLDRV 设置为 Load Me First 组的成员。下面是经过修改的 ServiceGroupOrder:
SCSI miniport
port
Primary disk
Load Me First
SCSI class
SCSI CDROM class
filter
boot file system
.
.
.
下面是 SAMPLDRV 的注册表项:
\registry\machine\system\currentcontrolset\services\sampldrv Type = REG_DWORD 0x00000001 Start = REG_DWORD 0x00000000 Group = Load Me First ErrorControl = REG_DWORD 0x00000000 DependOnGroup = REG_MULTI_SZ "SCSI miniport"
根据该配置,SAMPLDRV 将在 SCSIDISK 之前加载。
方法 2:GroupOrderList 和 Tag 值
称为 Tag 的可选项可以包括在设备驱动程序的注册表中。Tag 的值可以帮助决定某个组内设备驱动程序的加载顺序。加载顺序不必按数字顺序排列,相反,可以按照由 GroupOrderList 定义的顺序排列。GroupOrderList 中每个组的第一项都是 Tag 值的数值。接下来是要加载的 Tag 值的数字顺序。组中的设备驱动程序首先按照其由 GroupOrderList 所定义的 Tag 值进行加载。如果设备驱动程序没有 Tag 值,或者 Tag 值不在 GroupOrderList 中,则这些设备驱动程序将在加载具有有效 Tag 值的设备驱动程序之后进行加载。对于这些设备驱动程序,无法保证加载顺序,只能保证组中的所有设备驱动程序都在下一组加载之前进行加载。
下面是 GroupOrderList 的部分输出:
\registry\machine\system\currentcontrolset\control\grouporderlist Base = REG_BINARY 0d 00 00 00 01 00... Extended base = REG_BINARY 04 00 00 00 01 00... Filter = REG_BINARY 05 00 00 00 01 00... Keyboard Class = REG_BINARY 01 00 00 00 01 00... Keyboard Port = REG_BINARY 01 00 00 00 01 00... Ndis = REG_BINARY 09 00 00 00 01 00... Pointer Class = REG_BINARY 01 00 00 00 01 00... Pointer Port = REG_BINARY 03 00 00 00 01 00... . . .
注意:没有为 SCSI class 定义值。并非每个组都出现在 GroupOrderList 中。如果 GroupOrderList 中没有某个组,则无法保证组内设备驱动程序的加载顺序。
与 ServiceGroupOrder 一样,GroupOrderList 也可以修改。以上示例可以添加 SCSI class 的 Tag 项:
\registry\machine\system\currentcontrolset\control\grouporderlist SCSI class = REG_BINARY 02 00 00 00 02 00 00 00 01 00 00 00 Base = REG_BINARY 0d 00 00 00 01 00... Extended base = REG_BINARY 04 00 00 00 01 00... . . .
在这个示例中,SCSI class 组识别出两个 Tag 值:00000001 和 00000002。Tag 值的加载顺序是先加载 00000002,其次是 00000001。如果 SAMPLDRV 在 SCSI class 组中(与 SCSIDISK 相同),则任一 Tag 值都可以保证 SAMPLDRV 在 SCSIDISK 之前加载,因为 SCSIDISK 没有 Tag 值,而没有作标记的驱动程序将在组中最后一个加载。
如果由于某种原因,SCSIDISK 分配的 Tag 值是 0×00000001,则当 SAMPLDRV 分配的 Tag 值是 00000002 时,SAMPLDRV 在 SCSIDISK 之前加载:
\registry\machine\system\currentcontrolset\services\sampldrv Type = REG_DWORD 0x00000001 Start = REG_DWORD 0x00000000 Group = SCSI class ErrorControl = REG_DWORD 0x00000000 DependOnGroup = REG_MULTI_SZ "SCSI miniport" Tag = REG_DWORD 0x00000002
Keywords: kbhowto KB115486