MmLockPagableCodeSection 宏 (wdm.h)

MmLockPagableCodeSection 例程将驱动程序代码的一部分锁在系统空间中,其中包含一组用特殊编译器指令标记的驱动程序例程。

语法

void MmLockPagableCodeSection(
  [in]  Address
);

参数

[in] Address

指定符号地址。 此地址通常是驱动程序代码的一部分内驱动程序函数的名称,该部分已标记为 #pragma alloc_text(PAGExxxx,driverfunction)。 然后,保证在返回此函数时锁定 PAGExxxx 节中的所有函数。

返回值

没有

言论

mmLockPagableCodeSection 返回作系统用于标识驱动程序代码此部分的不透明值。 此不透明值随后可以传递给 MmLockPagableSectionByHandle(如果驱动程序解锁,然后重新锁定分区),或 MmUnlockPagableImageSection

mmLockPagableCodeSection 例程,mmUnlockPagableImageSection(执行相反作的例程)支持可以执行以下作的驱动程序:

  • 延迟将一部分驱动程序例程加载到常驻内存中,直到驱动程序设备的传入 I/O 请求使这些例程能够处理 IRP。

  • 使相同的驱动程序例程子集可用于分页时,它们已完成 I/O 请求的处理,并且当前不会对驱动程序的设备发出其他请求。

mmLockPagableCodeSectionmmLockPagableSectionByHandlemmUnlockPagableImageSection 适用于具有以下特征的设备和中间驱动程序:

  • 驱动程序具有在系统运行时可能不需要的代码路径,但如果需要,驱动程序的代码必须驻留,因为它在任意线程上下文中或在 IRQL >= DISPATCH_LEVEL运行。

  • 驱动程序可以确切地确定何时应加载可分页例程,以及何时可以再次分页。

例如,系统提供的容错磁盘驱动程序支持创建镜像集、条带集和卷集。 但是,只能使用镜像集配置特定计算机,仅使用条带集、仅使用卷集或这三种可能选项的任意组合。 在这些情况下,系统 ftdisk 驱动程序通过将显式支持镜像、条带和卷集的例程标记为属于可分页代码部分来减小其加载映像的大小。 在驱动程序初始化期间,仅当用户已将磁盘配置为具有镜像、条带或卷集时,可分页代码部分才会驻留。 如果用户动态重新分区磁盘,ftdisk 驱动程序会锁定支持用户请求的任何镜像、条带或卷集所需的任何其他可分页代码部分。

作为其他示例,系统提供的串行和并行驱动程序具有 DispatchCreateDispatchClose 例程,这些例程分别在为独占 I/O 打开特定端口和释放打开的端口的句柄时调用。 然而,串行和并行 I/O 请求是零星的,由最终用户当前运行的应用程序以及最终用户当前正在执行的应用程序选项决定。 在这些情况下,系统串行和并行驱动程序通过将许多例程标记为属于可分页代码部分(DispatchCreate 例程仅在为 I/O 打开第一个端口时才会驻留)来减少其加载图像的大小。

请注意,上述每个系统驱动程序都满足两个可分页节的条件:驱动程序具有运行系统时可能不需要的代码路径,驱动程序可以确切地确定其可分页节何时应加载,并且可以再次分页。

由于锁定分区是一项昂贵的作,因此,如果驱动程序在多个位置锁定可分页代码节,请对第一个请求使用 mmLockPagableCodeSection。 通过调用 MmLockPagableSectionByHandle 传递 mmLockPagableCodeSection返回的句柄来发出后续锁定请求。 通过句柄锁定可显著提高驱动程序性能,因为内存管理器使用不透明返回值快速查找相关部分,而不是搜索加载的模块列表。 通过调用 MmUnlockPagableImageSection来解锁锁定分区。

必须使用以下编译器指令标记可分页代码节中的每个驱动程序例程:

#pragma alloc_text(PAGExxxx, DriverRoutine)

其中,xxxx 是调用方可分页节的可选四个字符的唯一标识符,DriverRoutine 是要在可分页代码节中包含的入口点。 关键字 PAGE 和驱动程序确定的后缀(最多四个字符)区分大小写;也就是说,PAGE 必须大写。

例如,对 MmLockPagableCodeSection 的单个调用(例如,驱动程序的 DispatchCreate 例程)会导致整个部分(包含标记为同一 PAGExxxx 标识符)的整个部分被锁定在系统空间中。

某些类型的驱动程序例程不能成为任何驱动程序可分页部分的一部分,包括:

  • 切勿使 ISR 可分页。 即使设备设备未使用,设备驱动程序也可能会接收虚假中断,尤其是在可以共享中断向量时。 通常,即使驱动程序可以显式禁用设备上的中断,ISR 也不应进行分页。

  • 如果驱动程序无法控制 DPC 排队时间(例如任何 DpcForIsr可能从 ISR 排队的 CustomDpc 例程),则永远不要使 DPC 例程可分页。 通常,在 IRQL 上运行的驱动程序例程 >= DISPATCH_LEVEL,并且可以在任意线程上下文中调用或响应随机外部事件不应进行分页。

  • 切勿在任何可能属于系统分页 I/O 路径的驱动程序中 DispatchReadDispatchWrite 例程可分页。 可能包含系统页文件的磁盘的驱动程序必须具有 DispatchRead,并且 DispatchWrite 例程驻留在系统运行时,所有分层在此类磁盘驱动程序之上的驱动程序也必须如此。

请注意,用编译器指令标记的可分页节中的例程 #pragma alloc_text(PAGExxxx, ...) 不同于用编译器指令 #pragma alloc_text(INIT, ...)标记的例程。INIT 部分中的例程不可分页,只要驱动程序从其 DriverEnt ry 返回或其 重新初始化 例程(如果有),就会丢弃该例程。

内存管理器在任何驱动程序的可分页节上维护内部锁计数。 调用 mmLockPagableCodeSection 递增此计数,mmUnlockPagableImageSection 递减计数。 除非此计数为零,否则无法分页驱动程序的可分页节。

有关创建可分页代码部分的详细信息,请参阅 使驱动程序可分页

要求

要求 价值
目标平台 桌面
标头 wdm.h (包括 Wdm.h、Ntddk.h、Ntifs.h)
NtosKrnl.lib
DLL NtosKrnl.exe
IRQL <=APC_LEVEL

另请参阅

mmLockPagableDataSection

mmLockPagableSectionByHandle

mmPageEntireDriver

mmResetDriverPaging

mmUnlockPagableImageSection