FsRtlCancellableWaitForSingleObject 函数 (ntifs.h)

FsRtlCancellableWaitForSingleObject 例程对调度程序对象执行可取消的等待操作(可以终止的等待)。

语法

NTSTATUS FsRtlCancellableWaitForSingleObject(
  [in]           PVOID          Object,
  [in, optional] PLARGE_INTEGER Timeout,
  [in, optional] PIRP           Irp
);

参数

[in] Object

指向调用方为其提供存储的初始化调度程序对象的指针(事件、互斥体、信号灯、线程或计时器)。

[in, optional] Timeout

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

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

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

如果指定了 超时,则如果未在给定间隔过期时将对象设置为信号状态,则会自动满足等待。

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

[in, optional] Irp

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

返回值

FsRtlCancellableWaitForSingleObject 可以返回以下值之一:

返回代码 描述
STATUS_SUCCESS Object 参数指定的调度程序对象满足等待。
STATUS_TIMEOUT 在对象设置为信号状态之前发生超时。 当无法立即满足指定的等待条件集并且 超时 设置为零时,可以返回此值。
STATUS_ABANDONED_WAIT_0 调用方试图等待已放弃的互斥体。
STATUS_CANCELLED 等待被指定的 IRP 上的挂起取消请求中断。 请注意,仅当有效的 IRP 传递给 FsRtlCancellableWaitForSingleObject 且 IRP 已由 CancelSynchronousIo取消时,才会返回此值。
STATUS_THREAD_IS_TERMINATING 等待中断,因为线程已由应用程序或用户终止。

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

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

言论

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

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

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

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

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

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

下面的示例演示如何使用 FsRtlCancellableWaitForSingleObject 来支持I/O 完成/取消准则。

//
// sample calling routine
//
NTSTATUS ProcessIrpFromUserMode( PIRP pOriginalIrp, ... )
{
NTSTATUS  Status;
NTSTATUS  WaitStatus;
KEVENT   Event;
LARGE_INTEGERTimeout;
PIRP   pAdditionalIrp;
BOOLEAN  Cancelled;

 //
 // Allocate the additional IRP here:
 //
KeInitializeEvent( &Event,
            SynchronizationEvent,
    FALSE );
pContext->pEvent = &Event; // Driver specific context structure.
 IoSetCompletionRoutine( pAdditionalIrp,
 FunctionCompletionRoutine,
 pContext,
 TRUE,
 TRUE,
 TRUE);
 Status = IoCallDriver( pDeviceObject, pAdditionalIrp );
  if (Status == STATUS_PENDING) {
   //
   // Initialize Timeout variable here. If no timeout is needed, pass NULL for 
   // that parameter instead.
   //
  WaitStatus = FsRtlCancellableWaitForSingleObject( &Event, 
          &Timeout,
               pOriginalIrp );
   if ((WaitStatus == STATUS_CANCELLED) || (WaitStatus == STATUS_THREAD_IS_TERMINATING)) {
    //
    // Thread is terminating. IRP was canceled.       
    // Cancel the additional IRP passed to the lower level driver, cleanup, and return quickly.
    //
   Cancelled = IoCancelIrp( pAdditionalIrp );
    if (!Cancelled || KeReadStateEvent( &Event ) == 0) {
     //
     //  Wait for the IRP to complete. 
     // If cancel was posted successfully on the IRP, this shouldn't take a long time.
     //
    (VOID) KeWaitForSingleObject( &Event,
             Executive,
             KernelMode,        // WaitMode
             FALSE,             // Alertable
             (PLARGE_INTEGER) NULL );
   }
  } else if (WaitStatus == STATUS_TIMEOUT) {
    //
    // Wait timed out. The IRP was canceled or the API 
    // waited for the I/O to complete.
    // 
  } else {
   ASSERT( WaitStatus == STATUS_SUCCESS );
    //
    // The wait completed without timeout
    // or being canceled.
    //
  }
}
 //
 // IRP is valid and needs to be handled here.
 // pAdditionalIrp->IoStatus.Status contains the status of the IRP.
 // Finally, pOriginal IRP needs to be completed appropriately as well.
 //
}

//
// Sample completion routine:
//
NTSTATUS
FunctionCompletionRoutine(
  IN PDEVICE_OBJECT  pDeviceObject,
  INOUT PIRP  pAdditionalIrp,
  IN PVOID  pContext)
{
 if (pAdditionalIrp->PendingReturned) {
 KeSetEvent( pContext->pEvent, 0, FALSE );
}

 //
 // Discontinue I/O completion.
 // Dispatch routine will deal with IRP.
 //
 return STATUS_MORE_PROCESSING_REQUIRED;
}

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

FsRtlCancellableWaitForSingleObject 如果 IRQL 大于或等于APC_LEVEL且可选的 Irp 参数指向有效的 IRP,则会断言调试生成。

要求

要求 价值
最低支持的客户端 Windows Vista
目标平台 普遍
标头 ntifs.h (include Ntifs.h)
NtosKrnl.lib
DLL NtosKrnl.exe
IRQL 请参阅“备注”部分。
DDI 符合性规则 HwStorPortProhibitedDIS(storport)SpNoWait(storport)

另请参阅

ExInitializeFastMutex

FsRtlCancellableWaitForMultipleObjects

KeInitializeEvent

KeInitializeMutex

KeInitializeSemaphore

KeInitializeTimer

KeWaitForMultipleObjects

KeWaitForSingleObject