FsRtlCancellableWaitForSingleObject 함수(ntifs.h)
FsRtlCancellableWaitForSingleObject 루틴은 디스패처 개체에서 취소 가능한 대기 작업(종료될 수 있는 대기)을 실행합니다.
통사론
NTSTATUS FsRtlCancellableWaitForSingleObject(
[in] PVOID Object,
[in, optional] PLARGE_INTEGER Timeout,
[in, optional] PIRP Irp
);
매개 변수
[in] Object
호출자가 스토리지를 제공하는 초기화된 디스패처 개체(이벤트, 뮤텍스, 세마포, 스레드 또는 타이머)에 대한 포인터입니다.
[in, optional] Timeout
선택적 제한 시간 값에 대한 포인터입니다. 이 매개 변수는 대기가 완료될 절대 또는 상대 시간을 100나노초 단위로 지정합니다.
시간 제한 0 값(즉, *제한 시간 == 0)을 가리키는 경우 루틴은 기다리지 않고 반환됩니다. 호출자가 NULL 포인터(즉, 시간 제한 == NULL
양수 제한 시간 값은 1601년 1월 1일을 기준으로 절대 시간을 지정합니다. 음수 시간 제한 값은 현재 시간을 기준으로 간격을 지정합니다. 절대 만료 시간은 시스템 시간의 변경 내용을 추적합니다. 상대 만료 시간은 시스템 시간 변경의 영향을 받지 않습니다.
시간 제한 지정된 경우 지정된 간격이 만료될 때 개체가 신호 상태로 설정되지 않으면 대기가 자동으로 충족됩니다.
0의 제한 시간 값(즉, *시간 제한 == 0)을 사용하면 대기 조건 집합을 테스트하고 뮤텍스 획득과 같이 대기가 즉시 충족될 수 있는 경우 조건부로 추가 작업을 수행할 수 있습니다.
[in, optional] Irp
사용자가 발급하고 사용자가 취소할 수 있는 I/O 작업에 해당하는 원래 IRP에 대한 포인터입니다. 호출자는 IRP가 이 루틴 기간 동안 유효한 상태로 유지되고 IRP에 취소 루틴 집합이 없어야 합니다(예: IRP에서 IoSetCancelRoutine 호출되지 않아야
반환 값
FsRtlCancellableWaitForSingleObject 다음 값 중 하나를 반환할 수 있습니다.
반환 코드 | 묘사 |
---|---|
STATUS_SUCCESS | Object 매개 변수로 지정된 디스패처 개체가 대기를 충족했습니다. |
STATUS_TIMEOUT | 개체가 신호 상태로 설정되기 전에 시간 초과가 발생했습니다. 지정된 대기 조건 집합을 즉시 충족할 수 없고 시간 제한 0으로 설정된 경우 이 값을 반환할 수 있습니다. |
STATUS_ABANDONED_WAIT_0 | 호출자가 중단된 뮤텍스를 기다리려고 했습니다. |
STATUS_CANCELLED | 지정된 IRP에 대한 보류 중인 취소 요청에 의해 대기가 중단되었습니다. 이 값은 유효한 IRP가 FsRtlCancellableWaitForSingleObject 전달되고 CancelSynchronousIoIRP가 취소된 경우에만 반환됩니다. |
STATUS_THREAD_IS_TERMINATING | 스레드가 애플리케이션 또는 사용자에 의해 종료되면서 대기가 중단되었습니다. |
반환 값은 대기 상태만 나타냅니다. 해당하는 경우 원래 사용자 모드 IRP를 처리하는 과정에서 생성된 다른 IRP에서 직접 I/O 요청의 실제 상태를 가져와야 합니다.
NT_SUCCESS 매크로는 STATUS_CANCELLED FALSE("failure")를 반환하고 다른 모든 상태 값에 대해 상태 값과 STATUS_THREAD_IS_TERMINATING TRUE("success")를 반환합니다.
발언
FsRtlCancellableWaitForSingleObject 루틴은 디스패처 개체에서 취소 가능한 대기 작업을 실행합니다. 스레드가 사용자 또는 애플리케이션에 의해 종료되거나 CancelSynchronousIo 스레드와 연결된 스레드 IRP(동기 IRP)에 취소 요청을 게시하는 경우 대기가 취소됩니다.
예를 들어 리디렉터에서 사용자 모드 IRP를 처리하고 보조 IRP가 완료되기를 동기적으로 대기하기 위해 하나 이상의 보조 IRP를 만들어야 할 수 있습니다. 이 작업을 수행하는 한 가지 방법은 보조 IRP의 완료 루틴에 의해 신호를 받을 이벤트를 설정한 다음 이벤트가 신호를 받을 때까지 기다리는 것입니다. 그런 다음 취소 가능한 대기 작업을 수행하기 위해 FsRtlCancellableWaitForSingleObject 보조 IRP와 연결된 이벤트와 원래 사용자 모드 IRP를 전달하도록 호출됩니다. 보류 중인 종료 이벤트가 발생하거나 원래 사용자 모드 IRP가 취소된 경우 이벤트가 신호를 받을 때까지 스레드의 대기가 취소됩니다.
대기를 종료해도 호출자가 발급한 I/O 작업은 자동으로 취소되지 않으며 호출자가 별도로 처리해야 합니다.
FsRtlCancellableWaitForSingleObject 전달된 Object 매개 변수가 뮤텍스인 경우 특별한 고려 사항이 적용됩니다. 대기 중인 디스패처 개체가 뮤텍스인 경우 APC 배달은 대기 중에 다른 모든 디스패처 개체와 동일합니다. 그러나 FsRtlCancellableWaitForSingleObjects가 STATUS_SUCCESS 반환되고 스레드가 실제로 뮤텍스를 보유하면 특수 커널 모드 APC만 전달됩니다. 커널 모드와 사용자 모드 모두의 다른 모든 APC 배달은 사용하지 않도록 설정됩니다. APC 배달에 대한 이 제한은 뮤텍스가 해제될 때까지 유지됩니다.
뮤텍스는 MINLONG 시간만 재귀적으로 획득할 수 있습니다. 이 제한을 초과하면 루틴에서 STATUS_MUTANT_LIMIT_EXCEEDED 예외가 발생합니다.
다음은 I/O 완료/취소 지침지원하기 위해 FsRtlCancellableWaitForSingleObject 사용하는 방법의 예입니다.
//
// 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를 가리키는 경우 FsRtlCancellableWaitForSingleObject IRQL PASSIVE_LEVEL 호출해야 합니다.
Irp 매개 변수를 사용하지 않으면 APC_LEVEL 작거나 같은 IRQL에서 루틴을 호출할 수 있습니다. 필요한 경우
FsRtlCancellableWaitForSingleObject IRQL이 APC_LEVEL 크거나 같고 선택적 Irp 매개 변수가 유효한 IRP를 가리키는 경우 디버그 빌드에서 어설션됩니다.
요구 사항
요구 | 값 |
---|---|
지원되는 최소 클라이언트 | Windows Vista |
대상 플랫폼 | 보편적 |
헤더 | ntifs.h(Ntifs.h 포함) |
라이브러리 | NtosKrnl.lib |
DLL | NtosKrnl.exe |
IRQL |
설명 섹션을 참조하세요. |
DDI 규정 준수 규칙 |
HwStorPortProhibitedDDIs(storport), SpNoWait(storport) |
참고 항목
exInitializeFastMutex