在驅(qū)動程序中,經(jīng)常會調(diào)用其他的驅(qū)動程序;其中,手動構(gòu)造 IRP ,然后將 IRP 傳遞到相應驅(qū)動程序的派遣函數(shù)中是一種比較簡單的方法,下面就來介紹下手動創(chuàng)建 IRP 的幾種不同的方法及其特點。
創(chuàng)建 IRP 總共有 4 種方法。分別通過調(diào)用: IoBuildSynchronousFsdRequest 、 IoBuildAsynchronousFsdRequest 、 IoBuildDeviceIoControl 和 IoAllocateIrp 這 4 個內(nèi)核函數(shù)來完成。這其中, IoAllocateIrp 是比較底層的內(nèi)核函數(shù),其余的三個內(nèi)核函數(shù)是屬于靠近上層的內(nèi)核函數(shù),而且這三個函數(shù)都是通過調(diào)用 IoAllocateIrp 實現(xiàn)的。
這幾個函數(shù)都是文檔化的函數(shù),原型都可以在 DDK Documentation 中查到,這里就不多說了,下面主要來說說它們的不同點:
1. 可創(chuàng)建的 IRP 類型
這四個函數(shù)可以創(chuàng)建的 IRP 的類型是不同的。 IoBuildSynchronousFsdRequest 用于創(chuàng)建同步的 IRP 請求,但是只可以創(chuàng)建以下類型的 IRP : IRP_MJ_PNP ,IRP_MJ_READ,IRP_MJ_WRITE,IRP_MJ_FLUSH_BUFFERS 和IRP_MJ_SHUTDOWN ; IoBuildAsynchronousFsdRequest 可創(chuàng)建的 IRP 類型和 IoBuildSynchronousFsdRequest 一樣(從名字就可以看出來),只是它是用來創(chuàng)建異步的 IRP 請求。 IoBuildDeviceIoControl 可以創(chuàng)建的 IRP 類型為:IRP_MJ_DEVICE_CONTROL 和IRP_MJ_INTERNAL_DEVICE_CONTROL 。而且 IoBuildDeviceIoControl 只能創(chuàng)建同步的 IRP 。在這三個函數(shù)中,都有一個 ULONG 的輸入?yún)?shù)指定創(chuàng)建的 IRP 類型。 IoAllocateIrp 函數(shù)的使用比較靈活,他可以創(chuàng)建任意類型的 IRP ,但不是由參數(shù)指定,而是創(chuàng)建后自行填寫,要求用戶對 IRP 的結(jié)構(gòu)有比較熟悉的理解。
2. 創(chuàng)建后 IRP 對象的刪除
IoBuildSynchronousFsdRequest 、 IoBuildAsynchronousFsdRequest 和 IoBuildDeviceIoControl 內(nèi)核函數(shù)在創(chuàng)建完 IRP 后,不需要程序員負責刪除 IRP ,操作系統(tǒng)會自動刪除。而用 IoAllocateIrp 內(nèi)核函數(shù)創(chuàng)建 IRP 時,需要程序員自己調(diào)用 IoFreeIrp 內(nèi)核函數(shù)刪除 IRP 對象。
3. 關聯(lián)的事件
IoBuildSynchronousFsdRequest 和 IoBuildDeviceIoControl 在創(chuàng)建 IRP 時,需要為它們準備好一個事件,這個事件會和 IRP 請求相關聯(lián),當 IRP 請求被結(jié)束時該事件觸發(fā)。程序中要用 KeWaitForSingleObject 函數(shù)等待。 IoBuildAsynchronousFsdRequest 函數(shù)創(chuàng)建 IRP 時則不需要準備事件,不過可以通過 IRP 的 UserEvent 子域來通知 IRP 請求的結(jié)束。
當執(zhí)行 IoCompleteRequest 內(nèi)核函數(shù)時,操作系統(tǒng)會檢查 IRP 的 UserEvent 子域是否為空。如果該子域為空,則它代表一個事件指針,這時 IoCompleteRequest 會設置這個事件。
本文來自CSDN博客,轉(zhuǎn)載請標明出處:http://blog.csdn.net/vangoals/archive/2009/07/26/4381567.aspx