Fungsi FsRtlCancellableWaitForSingleObject (ntifs.h)
Rutinitas FsRtlCancellableWaitForSingleObject menjalankan operasi tunggu yang dapat dibatalkan (tunggu yang dapat dihentikan) pada objek dispatcher.
Sintaks
NTSTATUS FsRtlCancellableWaitForSingleObject(
[in] PVOID Object,
[in, optional] PLARGE_INTEGER Timeout,
[in, optional] PIRP Irp
);
Parameter
[in] Object
Penunjuk ke objek dispatcher yang diinisialisasi (peristiwa, mutex, semaphore, thread, atau timer) tempat penelepon memasok penyimpanan.
[in, optional] Timeout
Penunjuk ke nilai batas waktu opsional. Parameter ini menentukan waktu absolut atau relatif, dalam 100 unit nanodetik, tempat penantian selesai.
Jika Waktu habis menunjuk ke nilai nol (yaitu, *Batas Waktu == 0), rutinitas akan kembali tanpa menunggu. Jika penelepon memasok pointer NULL (yaitu, Timeout == NULL), rutinitas menunggu tanpa batas waktu hingga objek diatur ke status sinyal.
Nilai Batas Waktu positif menentukan waktu absolut, relatif terhadap 1 Januari 1601. Nilai Batas Waktu negatif menentukan interval relatif terhadap waktu saat ini. Waktu kedaluwarsa absolut melacak perubahan apa pun dalam waktu sistem. Waktu kedaluwarsa relatif tidak terpengaruh oleh perubahan waktu sistem.
Jika Batas Waktu ditentukan, penantian akan otomatis terpenuhi jika objek tidak diatur ke status tersinyal ketika interval yang diberikan kedaluwarsa.
Nilai waktu habis nol (yaitu, *Waktu Habis == 0) memungkinkan Anda menguji serangkaian kondisi tunggu, dan untuk melakukan tindakan tambahan secara kondisional jika penantian dapat segera terpenuhi, seperti dalam akuisisi mutex.
[in, optional] Irp
Penunjuk ke IRP asli yang sesuai dengan operasi I/O yang dikeluarkan oleh pengguna dan yang dapat dibatalkan oleh pengguna. Pemanggil harus memastikan bahwa IRP akan tetap valid selama durasi rutinitas ini dan bahwa IRP tidak boleh memiliki set rutin pembatalan (misalnya, IoSetCancelRoutine tidak boleh dipanggil pada IRP). Perhatikan bahwa IRP harus dipegang oleh pemanggil, IRP tidak dapat diteruskan ke driver tingkat bawah.
Nilai kembali
FsRtlCancellableWaitForSingleObject dapat mengembalikan salah satu nilai berikut:
Menampilkan kode | Deskripsi |
---|---|
STATUS_SUCCESS | Objek dispatcher yang ditentukan oleh parameter Object memenuhi waktu tunggu. |
STATUS_TIMEOUT | Waktu habis terjadi sebelum objek diatur ke status bersinyali. Nilai ini dapat dikembalikan ketika kumpulan kondisi tunggu yang ditentukan tidak dapat segera terpenuhi dan Batas Waktu diatur ke nol. |
STATUS_ABANDONED_WAIT_0 | Penelepon mencoba menunggu mutex yang telah ditinggalkan. |
STATUS_CANCELLED | Penantian terganggu oleh permintaan pembatalan yang tertunda pada IRP yang ditentukan. Perhatikan bahwa nilai ini dikembalikan hanya jika IRP yang valid diteruskan ke FsRtlCancellableWaitForSingleObject dan IRP dibatalkan oleh CancelSynchronousIo. |
STATUS_THREAD_IS_TERMINATING | Penantian terganggu karena utas telah dihentikan oleh aplikasi atau pengguna. |
Nilai yang dikembalikan hanya menunjukkan status tunggu. Jika berlaku, status aktual permintaan I/O harus diperoleh langsung dari IRP lain yang dihasilkan dalam proses penanganan IRP mode pengguna asli.
Perhatikan bahwa makro NT_SUCCESS mengembalikan FALSE ("kegagalan") untuk nilai status STATUS_CANCELLED dan STATUS_THREAD_IS_TERMINATING dan TRUE ("berhasil") untuk semua nilai status lainnya.
Keterangan
Rutinitas FsRtlCancellableWaitForSingleObject menjalankan operasi tunggu yang dapat dibatalkan pada objek dispatcher. Jika utas dihentikan oleh pengguna atau oleh aplikasi, atau jika CancelSynchronousIo memposting permintaan pembatalan pada IRP (IRP sinkron) yang terkait dengan utas, tunggu dibatalkan.
Rutinitas FsRtlCancellableWaitForSingleObject dirancang untuk mendukung Panduan Penyelesaian/Pembatalan I/O yang dimulai dengan Windows Vista. Tujuan dari pedoman ini adalah untuk memungkinkan pengguna (atau aplikasi) mengakhiri aplikasi dengan cepat. Ini, pada gilirannya, mengharuskan aplikasi memiliki kemampuan untuk dengan cepat mengakhiri utas yang menjalankan I/O serta operasi I/O saat ini. Rutinitas ini menyediakan cara bagi utas pengguna untuk memblokir (yaitu, tunggu) di kernel untuk penyelesaian I/O, objek dispatcher, atau variabel sinkronisasi dengan cara yang memungkinkan tunggu dibatalkan dengan mudah. Rutinitas ini juga memungkinkan penantian utas dihentikan jika utas dihentikan oleh pengguna atau aplikasi.
Misalnya, pengalih mungkin perlu membuat satu atau beberapa RUNP sekunder untuk memproses IRP mode pengguna dan secara sinkron menunggu RUNP sekunder selesai. Salah satu cara untuk melakukan ini adalah dengan menyiapkan peristiwa yang akan disinyalir oleh rutinitas penyelesaian IRP sekunder dan kemudian menunggu peristiwa tersebut disinyalir. Kemudian, untuk melakukan operasi tunggu yang dapat dibatalkan, FsRtlCancellableWaitForSingleObject disebut melewati peristiwa yang terkait dengan IRP sekunder, serta IRP mode pengguna asli. Penantian utas untuk peristiwa yang akan disinyalir dibatalkan jika peristiwa penghentian yang tertunda terjadi atau jika IRP mode pengguna asli dibatalkan.
Perhatikan bahwa mengakhiri tunggu tidak secara otomatis membatalkan operasi I/O apa pun yang dikeluarkan oleh pemanggil - yang harus ditangani secara terpisah oleh pemanggil.
Pertimbangan khusus berlaku ketika parameter Objek yang diteruskan ke FsRtlCancellableWaitForSingleObject adalah mutex. Jika objek dispatcher yang ditunggu adalah mutex, pengiriman APC sama dengan untuk semua objek dispatcher lainnya selama menunggu. Namun, setelah FsRtlCancellableWaitForSingleObjects kembali dengan STATUS_SUCCESS dan utas benar-benar memegang mutex, hanya APC mode kernel khusus yang dikirimkan. Pengiriman semua APC lainnya, baik mode kernel maupun mode pengguna, dinonaktifkan. Pembatasan pengiriman APC ini berlanjut hingga mutex dirilis.
Mutex hanya dapat diperoleh secara rekursif waktu MINLONG. Jika batas ini terlampaui, rutinitas akan menimbulkan pengecualian STATUS_MUTANT_LIMIT_EXCEEDED.
Berikut ini adalah contoh cara menggunakan FsRtlCancellableWaitForSingleObject untuk mendukung Pedoman Penyelesaian/Pembatalan 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;
}
FsRtlCancellableWaitForSingleObject harus dipanggil di IRQL PASSIVE_LEVEL jika parameter Irp opsional menunjuk ke IRP yang valid. Jika parameter Irp tidak digunakan, rutinitas dapat dipanggil di IRQL kurang atau sama dengan APC_LEVEL. APC kernel normal dapat dinonaktifkan oleh pemanggil, jika diperlukan, dengan memanggil rutinitas KeEnterCriticalRegion atau FsRtlEnterFileSystem . Namun, APC kernel khusus tidak boleh dinonaktifkan.
FsRtlCancellableWaitForSingleObject akan menegaskan pada build debug jika IRQL lebih besar atau sama dengan APC_LEVEL dan parameter Irp opsional menunjuk ke IRP yang valid.
Persyaratan
Persyaratan | Nilai |
---|---|
Klien minimum yang didukung | Windows Vista |
Target Platform | Universal |
Header | ntifs.h (termasuk Ntifs.h) |
Pustaka | NtosKrnl.lib |
DLL | NtosKrnl.exe |
IRQL | Lihat bagian Keterangan. |
Aturan kepatuhan DDI | HwStorPortProhibitedDDIs(storport), SpNoWait(storport) |