FsRtlCancellableWaitForSingleObject 函式 (ntifs.h)
FsRtlCancellableWaitForSingleObject 例程會執行可取消的等候作業, (可以在發送器對象上終止) 等候。
語法
NTSTATUS FsRtlCancellableWaitForSingleObject(
[in] PVOID Object,
[in, optional] PLARGE_INTEGER Timeout,
[in, optional] PIRP Irp
);
參數
[in] Object
初始化發送器物件的指標, (事件、mutex、號誌、線程或定時器) ,呼叫者會為其提供記憶體。
[in, optional] Timeout
選擇性逾時值的指標。 此參數會以 100 奈秒的單位指定絕對或相對時間,等候完成。
如果 Timeout 指向零值 (即 *Timeout == 0) ,則例程會傳回而不等候。 如果呼叫端 (提供 NULL 指標,也就是 Timeout == NULL) ,則例程會無限期等候,直到物件設定為訊號狀態為止。
正 逾時 值會指定絕對時間,相對於 1601 年 1 月 1 日。 負 逾時 值會指定相對於目前時間的間隔。 絕對到期時間會追蹤系統時間中的任何變更。 相對到期時間不會受到系統時間變更的影響。
如果指定 Timeout ,當指定的間隔到期時,如果物件未設定為訊號狀態,就會自動滿足等候。
零 (逾時值,也就是 *Timeout == 0) 可讓您測試一組等候條件,並在等候可立即滿足時有條件地執行任何其他動作,如同取得 mutex 一樣。
[in, optional] Irp
與使用者發出且可由使用者取消之 I/O 作業相對應之原始 IRP 的指標。 呼叫端必須確定 IRP 在這段例程期間仍有效,而且 IRP 不能有取消例程集 (例如 ,IoSetCancelRoutine 不得在 IRP) 上呼叫。 請注意,呼叫端必須持有 IRP,它無法傳遞至較低層級的驅動程式。
傳回值
FsRtlCancellableWaitForSingleObject 可以傳回下列其中一個值:
傳回碼 | Description |
---|---|
STATUS_SUCCESS | Object 參數所指定的發送器對象滿足等候。 |
STATUS_TIMEOUT | 物件設定為訊號狀態之前發生逾時。 當指定的等候條件集無法立即符合且 Timeout 設定為零時,可以傳回此值。 |
STATUS_ABANDONED_WAIT_0 | 呼叫端嘗試等候已放棄的 Mutex。 |
STATUS_CANCELLED | 等候因指定 IRP 上的擱置取消要求而中斷。 請注意,只有當有效的 IRP 傳遞至 FsRtlCancellableWaitForSingleObject 且 取消了 CancelSynchronousIo 取消 IRP 時,才會傳回此值。 |
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 作業, 必須由呼叫端個別處理。
當傳遞至 FsRtlCancellableWaitForSingleObject 的 Object 參數是 mutex 時,適用特殊考慮。 如果等候的發送器對像是 mutex,則 APC 傳遞與等候期間所有其他發送器物件相同。 不過,一旦 FsRtlCancellableWaitForSingleObjects 傳回STATUS_SUCCESS,且線程實際上會保存 mutex,只會傳遞特殊的內核模式 APC。 已停用核心模式和使用者模式的所有其他 APC 傳遞。 在釋放 mutex 之前,傳遞 APC 的限制會持續存在。
Mutex 只能以遞歸方式取得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。 呼叫者可以視需要呼叫 KeEnterCriticalRegion 或 FsRtlEnterFileSystem 例程來停用一般核心 APC。 不過,不得停用特殊核心 APC。
如果 IRQL 大於或等於APC_LEVEL,且選擇性 Irp 參數指向有效的 IRP,FsRtlCancellableWaitForSingleObject 將會判斷提示偵錯組建。
規格需求
需求 | 值 |
---|---|
最低支援的用戶端 | Windows Vista |
目標平台 | Universal |
標頭 | ntifs.h (包含 Ntifs.h) |
程式庫 | NtosKrnl.lib |
Dll | NtosKrnl.exe |
IRQL | 請參閱一節。 |
DDI 合規性規則 | HwStorPortProhibitedDIS (storport) 、 SpNoWait (storport) |
另請參閱
意見反應
https://aka.ms/ContentUserFeedback。
即將登場:在 2024 年,我們將逐步淘汰 GitHub 問題作為內容的意見反應機制,並將它取代為新的意見反應系統。 如需詳細資訊,請參閱:提交並檢視相關的意見反應