FsRtlCancellableWaitForMultipleObjects 函数 (ntifs.h)

FsRtlCancellableWaitForMultipleObjects 例程执行可取消的等待操作, (可在一个或多个调度程序对象) 终止的等待操作。

语法

NTSTATUS FsRtlCancellableWaitForMultipleObjects(
  [in]           ULONG          Count,
  [in]           PVOID []       ObjectArray,
  [in]           WAIT_TYPE      WaitType,
  [in, optional] PLARGE_INTEGER Timeout,
  [in, optional] PKWAIT_BLOCK   WaitBlockArray,
  [in, optional] PIRP           Irp
);

参数

[in] Count

要等待的对象数。

[in] ObjectArray

指向调度程序对象的指针数组的指针,这些对象 (调用方为其提供存储的事件、互斥体、信号灯、线程和计时器) 。

[in] WaitType

任一 WaitAll,指示所有指定的对象都必须在满足等待前达到信号状态;或 WaitAny,指示任何一个对象都必须在满足等待之前达到信号状态。

[in, optional] Timeout

指向可选超时值的指针。 此参数指定完成等待的绝对时间或相对时间(以 100 纳秒为单位)。

如果 Timeout 指向零值 (即 *Timeout == 0) ,则例程返回而不等待。 如果调用方提供 NULL 指针 (即 Timeout == NULL) ,则例程将无限期等待,直到将任何或所有调度程序对象设置为信号状态。

正值指定相对于 1601 年 1 月 1 日绝对时间。 负值指定相对于当前时间的间隔。 绝对过期时间跟踪系统时间中的任何更改;相对过期时间不受系统时间更改的影响。

如果指定了 Timeout ,则当给定的间隔过期时,如果未满足任何指定的等待条件,则将自动满足等待。

超时值为零 (即*Timeout == 0) 允许测试一组等待条件,并在可以立即满足等待条件的情况下有条件地执行任何其他操作,如获取互斥。

[in, optional] WaitBlockArray

如果 Count<= THREAD_WAIT_OBJECTS, 则 WaitBlockArray 可以为 NULL。 否则,此参数必须指向字节的 sizeof(KWAIT_BLOCK * Count) 内存缓冲区。 例程在执行等待操作时使用此缓冲区进行记录保留。

[in, optional] Irp

指向原始 IRP 的指针,该指针对应于用户发出且可由用户取消的 I/O 操作。 调用方必须确保 IRP 在此例程期间保持有效,并且 IRP 不得设置取消例程 (例如,不得在 IRP) 上调用 IoSetCancelRoutine 。 请注意,IRP 必须由调用方持有,不能传递给较低级别的驱动程序。

返回值

FsRtlCancellableWaitForMultipleObjects 可以返回以下值之一:

返回代码 说明
STATUS_SUCCESS WaitType 参数指定的调用方和 ObjectArray 数组中的所有调度程序对象都已设置为信号状态。
STATUS_TIMEOUT 在满足指定的等待条件集之前发生超时。 当无法立即满足指定的等待条件集并且 Timeout 设置为零时,可以返回此值。
通过STATUS_WAIT_63 STATUS_WAIT_0 WaitType 指定的调用方和 ObjectArray 数组中的一个调度程序对象已设置为信号状态。 返回值的低 6 位对满足等待的 对象的从零开始的索引进行编码。
通过STATUS_ABANDONED_WAIT_63 STATUS_ABANDONED_WAIT_0 调用方试图等待已放弃的互斥体。 返回值的低六位对 ObjectArray 数组中互斥体从零开始的索引进行编码。
STATUS_CANCELLED 等待因指定 IRP 上的挂起取消请求而中断。 请注意,仅当有效的 IRP 传递给 FsRtlCancellableWaitForMultipleObjects 并且 IRP 已被 CancelSynchronousIo 取消时,才会返回此值。
STATUS_THREAD_IS_TERMINATING 等待中断,因为线程已被应用程序或用户终止。

返回值仅指示等待状态。 如果适用,应直接从处理原始用户模式 IRP 的过程中生成的另一个 IRP 获取 I/O 请求的实际状态。

请注意,对于STATUS_CANCELLED和STATUS_THREAD_IS_TERMINATING状态值,NT_SUCCESS宏返回 FALSE (“failure”) ,所有其他状态值返回 TRUE (“success”) 。

注解

FsRtlCancellableWaitForMultipleObjects 例程对调度程序对象执行可取消的等待操作。 如果线程由用户或应用程序终止,或者 CancelSynchronousIo 在与线程关联的线程 IRP (同步 IRP) 上发布取消请求,则取消等待。

FsRtlCancellableWaitForMultipleObjects 例程旨在支持从 Windows Vista 开始的 I/O 完成/取消指南。 这些准则的目标是允许用户 (或应用程序) 快速终止应用程序。 这反过来又要求应用程序能够快速终止正在执行 I/O 以及任何当前 I/O 操作的线程。 此例程为用户提供了一种阻止 (的方法,即在内核中等待 I/O 完成、调度程序对象或同步变量的) ,以便轻松取消等待。 如果线程被用户或应用程序终止,此例程还允许线程等待终止。

例如,重定向程序可能需要创建一个或多个辅助 IRP 才能处理用户模式 IRP,并同步等待辅助 IRP 完成。 执行此操作的一种方法是设置一个事件,该事件将由辅助 IRP 的完成例程发出信号,然后等待事件发出信号。 然后,为了执行可取消的等待操作, 将调用 FsRtlCancellableWaitForMultipleObjects ,传入与辅助 IRP 以及原始用户模式 IRP 关联的事件。 如果发生挂起的终止事件或取消原始用户模式 IRP,则取消线程等待事件发出信号。

请注意,终止等待不会自动取消调用方发出的任何 I/O 操作 - 必须由调用方单独处理。

每个线程对象都有一个内置的等待块数组,可用于同时等待多个对象。 应尽可能在等待多次操作中使用内置的等待块数组,因为无需分配额外的等待块存储,以后无需解除分配。 但是,如果必须同时等待的对象数大于内置等待块的数目,请使用 WaitBlockArray 参数指定要在等待操作中使用的备用等待块集。 驱动程序只需为 WaitBlockArray 分配足够大的内存缓冲区。 缓冲区不需要初始化,驱动程序可以将它视为不透明结构。 例程返回后,可以释放缓冲区。

如果 Count 大于 MAXIMUM_WAIT_OBJECTS 或 WaitBlockArray 为 NULL 且 Count 大于 THREAD_WAIT_OBJECTS,系统将 发出 bug 检查0xC:MAXIMUM_WAIT_OBJECTS_EXCEEDED

当传递给 FsRtlCancellableWaitForMultipleObjectsObjectArray 参数是互斥体时,需要特别注意。 如果等待的调度程序对象是互斥体,则 APC 传递与等待期间所有其他调度程序对象的传递相同。 但是,一旦 FsRtlCancellableWaitForMultipleObjects 返回并STATUS_SUCCESS且线程实际持有互斥体,则仅传递特殊的内核模式 APC。 禁用所有其他 APC(内核模式和用户模式)的传递。 在释放互斥体之前,对 APC 的传递限制一直存在。

互斥体只能以递归方式获取 MINLONG 时间。 如果超出此限制,则例程将引发STATUS_MUTANT_LIMIT_EXCEEDED异常。

如果可选的 Irp 参数指向有效的 IRP,则必须在 IRQL PASSIVE_LEVEL调用 FsRtlCancellableWaitForMultipleObjects。 如果未使用 Irp 参数,则可以在 IRQL 中调用该例程,小于或等于 APC_LEVEL。 如果需要,调用方可以通过调用 KeEnterCriticalRegionFsRtlEnterFileSystem 例程来禁用普通内核 APC。 但是,不能禁用特殊内核 APC。

如果 IRQL 大于或等于 APC_LEVEL并且 Irp 参数指向有效的 IRP,FsRtlCancellableWaitForMultipleObjects 将在调试版本中断言。

要求

要求
最低受支持的客户端 Windows Vista
目标平台 通用
标头 ntifs.h (包括 Ntifs.h)
Library NtosKrnl.lib
DLL NtosKrnl.exe
IRQL 请参见“备注”部分。
DDI 符合性规则 HwStorPortProhibitedDDI (storport) PowerIrpDDis (wdm) SpNoWait (storport)

另请参阅

ExInitializeFastMutex

FsRtlCancellableWaitForSingleObject

KeInitializeEvent

KeInitializeMutex

KeInitializeSemaphore

KeInitializeTimer

KeWaitForMultipleObjects

KeWaitForSingleObject

KeWaitForMutexObject