Tips SistemThis article applies to a different operating system than the one you are using. Article content that may not be relevant to you is disabled.
Salah satu tugas yang paling sering dilakukan di Windows Driver Model
Driver (WDM) mengirimkan permintaan input/output paket (IRPs) dari satu driver untuk
driver yang lain. Sopir baik menciptakan IRP sendiri dan mengirimnya ke yang lebih rendah
driver, atau pengandar ke depan IRPs yang diterima dari driver yang lain
yang terpasang di atas.
Artikel ini membahas semua kemungkinan cara
bahwa sopir dapat mengirim IRPs untuk pengandar yang lebih rendah dengan beranotasi contoh kode.
Tergantung pada kebutuhan, sopir penulis dapat mengikuti salah satu template yang diberikan dalam
Artikel ini dan tidak akan terpengaruh oleh lama IRP penanganan aturan.
Bagian 1
Hal ini menunjukkan 5 skenario tentang bagaimana untuk meneruskan IRP ke pengandar lain
dari rutin pengiriman, dan 7 skenario yang tersisa (tercantum di bagian 2
Hal ini) membahas cara-cara yang berbeda untuk menciptakan IRP dan mengirimnya ke
driver yang lain. Bagian 2 dari subjek ini terkandung dalam pengetahuan berikut
Artikel Base:
326315
(http://support.microsoft.com/kb/326315/
)
Cara menangani IRPs - contekan (bagian 2 dari 2)
Sebelum Anda memeriksa berbagai skenario, catatan
berikut tentang STATUS yang dikembalikan oleh rutinitas selesai:
IRP penyelesaian rutin dapat kembali STATUS_MORE_PROCESSING_REQUIRED atau STATUS_SUCCESS.
Manajer IO menggunakan aturan berikut ketika mengkaji
status:
Jika status STATUS_MORE_PROCESSING_REQUIRED, berhenti
menyelesaikan IRP, meninggalkan lokasi memori yang tidak berubah dan kembali.
Jika status apa-apa selain
STATUS_MORE_PROCESSING_REQUIRED, Lanjutkan menyelesaikan IRP ke atas.
Karena manajer IO tidak perlu tahu yang
nilai non-STATUS_MORE_PROCESSING_REQUIRED digunakan, menggunakan STATUS_SUCCESS (karena
nilai 0 efisien loadable pada sebagian besar arsitektur prosesor).
Untuk meningkatkan keterbacaan kode, Windows XP SP1 dan Windows
XP.NET Driver Development Kit Ntddk.h dan Wdm.h file header akan memiliki baru # define yang bernama STATUS_CONTINUE_COMPLETION, yang adalah alias untuk
STATUS_SUCCESS seperti yang ditunjukkan dalam kode berikut:
//
// This value should be returned from completion routines to continue
// completing the IRP upwards. Otherwise, STATUS_MORE_PROCESSING_REQUIRED
// should be returned.
//
#define STATUS_CONTINUE_COMPLETION STATUS_SUCCESS
//
// Completion routines can also use this enumeration instead of status codes.
//
typedef enum _IO_COMPLETION_ROUTINE_RESULT {
ContinueCompletion = STATUS_CONTINUE_COMPLETION,
StopCompletion = STATUS_MORE_PROCESSING_REQUIRED
} IO_COMPLETION_ROUTINE_RESULT, *PIO_COMPLETION_ROUTINE_RESULT;
Gunakan kode berikut jika pengandar hanya ingin meneruskan IRP
bawah dan tidak mengambil tambahan tindakan. Pengemudi tidak perlu menetapkan
penyelesaian rutin dalam hal ini. Jika pengemudi adalah tingkat atas driver, IRP
dapat diselesaikan serentak atau asynchronously, tergantung pada status yang
dikembalikan oleh pengandar yang lebih rendah.
NTSTATUS
DispatchRoutine_1(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
//
// You are not setting a completion routine, so just skip the stack
// location because it provides better performance.
//
IoSkipCurrentIrpStackLocation (Irp);
return IoCallDriver(TopOfDeviceStack, Irp);
}
Gunakan kode berikut jika pengemudi ingin meneruskan IRP untuk
rendah driver dan menunggu untuk itu untuk kembali sehingga dapat memproses IRP. Ini adalah
sering dilakukan ketika menangani PNP IRPs. Sebagai contoh, ketika Anda menerima
IRP_MN_START_DEVICE IRP, Anda harus meneruskan IRP ke sopir bus dan
menunggu untuk itu untuk menyelesaikan sebelum Anda dapat mulai perangkat Anda. Sistem Windows XP
memiliki fungsi baru bernama IoForwardIrpSynchronously yang dapat Anda gunakan untuk melakukan operasi ini dengan mudah.
NTSTATUS
DispatchRoutine_2(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
KEVENT event;
NTSTATUS status;
KeInitializeEvent(&event, NotificationEvent, FALSE);
//
// You are setting completion routine, so you must copy
// current stack location to the next. You cannot skip a location
// here.
//
IoCopyCurrentIrpStackLocationToNext(Irp);
IoSetCompletionRoutine(Irp,
CompletionRoutine_2,
&event,
TRUE,
TRUE,
TRUE
);
status = IoCallDriver(TopOfDeviceStack, Irp);
if (status == STATUS_PENDING) {
KeWaitForSingleObject(&event,
Executive, // WaitReason
KernelMode, // must be Kernelmode to prevent the stack getting paged out
FALSE,
NULL // indefinite wait
);
status = Irp->IoStatus.Status;
}
// <---- Do your own work here.
//
// Because you stopped the completion of the IRP in the CompletionRoutine
// by returning STATUS_MORE_PROCESSING_REQUIRED, you must call
// IoCompleteRequest here.
//
IoCompleteRequest (Irp, IO_NO_INCREMENT);
return status;
}
NTSTATUS
CompletionRoutine_2(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
)
{
if (Irp->PendingReturned == TRUE) {
//
// You will set the event only if the lower driver has returned
// STATUS_PENDING earlier. This optimization removes the need to
// call KeSetEvent unnecessarily and improves performance because the
// system does not have to acquire an internal lock.
//
KeSetEvent ((PKEVENT) Context, IO_NO_INCREMENT, FALSE);
}
// This is the only status you can return.
return STATUS_MORE_PROCESSING_REQUIRED;
}
Dalam kasus ini, pengemudi menetapkan penyelesaian yang rutin, ke depan
IRP turun, dan kemudian kembali status lebih rendah driver seperti. Tujuan
pengaturan penyelesaian rutin adalah untuk memodifikasi konten IRP dalam perjalanan
kembali.
NTSTATUS
DispathRoutine_3(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
NTSTATUS status;
//
// Because you are setting completion routine, you must copy the
// current stack location to the next. You cannot skip a location
// here.
//
IoCopyCurrentIrpStackLocationToNext(Irp);
IoSetCompletionRoutine(Irp,
CompletionRoutine_31,// or CompletionRoutine_32
NULL,
TRUE,
TRUE,
TRUE
);
return IoCallDriver(TopOfDeviceStack, Irp);
}
Jika Anda mengembalikan status pengandar yang lebih rendah dari pengiriman Anda
rutin:
Anda harus mengubah status IRP dalam penyelesaian
rutin. Ini adalah untuk memastikan bahwa nilai-nilai status ditetapkan dalam IRP IoStatus
blok (Irp-> IoStatus.Status) adalah sama dengan status kembali rendah
driver.
Anda harus menyebarkan pending status IRP sebagai
ditunjukkan oleh Irp-> PendingReturned.
Anda harus mengubah sinkronisitas dari
IRP.
Akibatnya, hanya ada 2 versi yang sah dari penyelesaian
rutin dalam skenario ini (31 dan 32):
NTSTATUS
CompletionRoutine_31 (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
)
{
//
// Because the dispatch routine is returning the status of lower driver
// as is, you must do the following:
//
if (Irp->PendingReturned) {
IoMarkIrpPending( Irp );
}
return STATUS_CONTINUE_COMPLETION ; // Make sure of same synchronicity
}
NTSTATUS
CompletionRoutine_32 (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
)
{
//
// Because the dispatch routine is returning the status of lower driver
// as is, you must do the following:
//
if (Irp->PendingReturned) {
IoMarkIrpPending( Irp );
}
//
// To make sure of the same synchronicity, complete the IRP here.
// You cannot complete the IRP later in another thread because the
// the dispatch routine is returning the status returned by the lower
// driver as is.
//
IoCompleteRequest( Irp, IO_NO_INCREMENT);
//
// Although this is an unusual completion routine that you rarely see,
// it is discussed here to address all possible ways to handle IRPs.
//
return STATUS_MORE_PROCESSING_REQUIRED;
}
Skenario 4: Antrian untuk kemudian, atau maju dan kembali
Menggunakan potongan kode berikut dalam situasi di mana pengandar
ingin baik antrian IRP dan proses kemudian atau meneruskan IRP untuk
rendah driver dan kembali untuk jumlah tertentu kali sebelum menyelesaikan
IRP. Pengiriman rutin menandai IRP tertunda dan kembali STATUS_PENDING
karena IRP akan selesai kemudian dalam thread berbeda. Di sini,
penyelesaian rutin dapat mengubah status IRP jika diperlukan (berbeda dengan
skenario sebelumnya).
NTSTATUS
DispathRoutine_4(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
NTSTATUS status;
//
// You mark the IRP pending if you are intending to queue the IRP
// and process it later. If you are intending to forward the IRP
// directly, use one of the methods discussed earlier in this article.
//
IoMarkIrpPending( Irp );
//
// For demonstration purposes: this IRP is forwarded to the lower driver.
//
IoCopyCurrentIrpStackLocationToNext(Irp);
IoSetCompletionRoutine(Irp,
CompletionRoutine_41, // or CompletionRoutine_42
NULL,
TRUE,
TRUE,
TRUE
);
IoCallDriver(TopOfDeviceStack, Irp);
//
// Because you marked the IRP pending, you must return pending,
// regardless of the status of returned by IoCallDriver.
//
return STATUS_PENDING ;
}
Rutin selesai baik dapat kembali STATUS_CONTINUE_COMPLETION atau
STATUS_MORE_PROCESSING_REQUIRED. Anda kembali STATUS_MORE_PROCESSING_REQUIRED
hanya jika Anda berniat untuk menggunakan kembali IRP dari thread lain dan menyelesaikan kemudian.
NTSTATUS
CompletionRoutine_41(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
)
{
//
// By returning STATUS_CONTINUE_COMPLETION , you are relinquishing the
// ownership of the IRP. You cannot touch the IRP after this.
//
return STATUS_CONTINUE_COMPLETION ;
}
NTSTATUS
CompletionRoutine_42 (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
)
{
//
// Because you are stopping the completion of the IRP by returning the
// following status, you must complete the IRP later.
//
return STATUS_MORE_PROCESSING_REQUIRED ;
}
Skenario 5: Menyelesaikan IRP dalam rutin pengiriman
Skenario ini menunjukkan bagaimana untuk menyelesaikan IRP dalam pengiriman
rutin.
Penting Ketika Anda menyelesaikan IRP dalam pengiriman rutin, kembali
status pengiriman rutin harus sesuai status nilai yang ditetapkan
di blok IoStatus IRP (Irp-> IoStatus.Status).
NTSTATUS
DispatchRoutine_5(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
//
// <-- Process the IRP here.
//
Irp->IoStatus.Status = STATUS_XXX;
Irp->IoStatus.Information = YYY;
IoCompletRequest(Irp, IO_NO_INCREMENT);
return STATUS_XXX;
}
PENTING: Artikel ini diterjemahkan menggunakan perangkat lunak mesin penerjemah Microsoft dan bukan oleh seorang penerjemah. Microsoft menawarkan artikel yang diterjemahkan oleh seorang penerjemah maupun artikel yang diterjemahkan menggunakan mesin sehingga Anda akan memiliki akses ke seluruh artikel baru yang diterbitkan di Pangkalan Pengetahuan (Knowledge Base) dalam bahasa yang Anda gunakan. Namun, artikel yang diterjemahkan menggunakan mesin tidak selalu sempurna. Artikel tersebut mungkin memiliki kesalahan kosa kata, sintaksis, atau tata bahasa, hampir sama seperti orang asing yang berbicara dalam bahasa Anda. Microsoft tidak bertanggung jawab terhadap akurasi, kesalahan atau kerusakan yang disebabkan karena kesalahan penerjemahan konten atau penggunaannya oleh para pelanggan. Microsoft juga sering memperbarui perangkat lunak mesin penerjemah.
Klik disini untuk melihat versi Inggris dari artikel ini:320275
(http://support.microsoft.com/kb/320275/en-us/
)
Seberapa besar upaya Anda untuk menggunakan artikel ini?
Sangat sedikit
Sedikit
Sedang
Besar
Sangat besar
Berikan saran tentang apa yang dapat kami lakukan untuk menyempurnakan informasi ini
Terima kasih! Masukan Anda akan digunakan untuk membantu kami meningkatkan konten dukungan. Untuk opsi bantuan lainnya, kunjungi Halaman Beranda Bantuan dan Dukungan.