IRP 處理流程

2021-07-23 06:25:19 字數 2791 閱讀 4047

本文通過開啟乙個檔案物件為例子,描述了乙個帶有兩個i/o stack location的irp的詳細處理過程。當然乙個irp可以有多個i/o stack location,具體個數取決於將要處理該請求的驅動的層數。下圖詳細描述了驅動程式是如何通過使用i/o支援例程(io*** routines)來處理irp以此來實現對相應檔案的讀寫操作。

1:i/o管理器呼叫檔案系統驅動(fsd)並把包含了子系統讀/寫請求的irp傳遞給該驅動。 fsd訪問irp中的i/o stack location, 從而決定應該執行什麼操作。

2:通過單此或者多次呼叫例程(ioallocateirp)來分配附加的irp,fsd就可以把原始的請求分成幾個小的請求(對於裝置驅動不只乙個的情況)。這些附加的irp中的i/o stack location區域將會被下一級的驅動填充成零返回給fsd,正因為如此,fsd可以重複使用原始的irp, 而不是向前面所講的那樣執行分配額外的irp,並在這些irp中建立針對下一層驅動的i/o stack location 並傳送給下一層驅動。

3:對每乙個驅動分配的irp,如前面所述,fsd將呼叫i/o支援例程來註冊乙個由fsd提供的完成例程;在完成例程中,fsd可以判定下級驅動是否滿足該請求,並且當下級驅動成功完成該irp時釋放該irp。i/o管理器將呼叫fsd提供的完成例程來判斷分配給驅動的irp是成功完成了,還是完成了但有錯誤,或者是被取消了。上層驅動負責釋放該驅動自己為下層驅動分配並設定的irp。i/o管理器負責示釋放它本身分配的並且被驅動完成的irp。接下來,為了建立傳遞給下層驅動執行的請求,fsd將呼叫i/o支援例程(iogetnextirpstacklocation)來訪問下層驅動的i/o stack location。(本例中,下一層驅動就是最後一層驅動)最後,fsd呼叫例程(iocalldriver)將irp傳遞給下一層驅動。

4:當irp傳遞到下層驅動時,該驅動檢查它對應的i/o stack location以此來判斷自己在目標裝置上該執行何種操作(由irp_mj_***之類的功能**決定)。在指定的i/o stack location中已經把相應的目標裝置通過裝置物件抽象表徵出來並出傳遞給本層驅動程式了。最底層的驅動可以做如下假設:i/o管理器把irp**給驅動的入口點,該入口點裡面,驅動已經定義好了各種irp_mj_***操作(本例中是irp_mj_read或者irp_mj_write),而且上層的驅動已經對該請求的引數的有效性進行了檢查。

如果沒有上層驅動,那麼底層驅動就要為針對irp_mj_***操作的引數的有效性進行檢查,如果有效, 驅動程式通常呼叫i/o 支援例程來通知i/o管理器該層裝置是將irp掛起了,還是將irp移入佇列裡等待,還是直接將irp**給由其他驅動提供的訪問目標裝置的驅動應用例程(此例中是乙個物理或者邏輯裝置: 磁碟或者分割槽)。

5: i/o管理器先判斷驅動程式是否在忙於處理其他irp,如果忙,則將irp移入佇列,並返回。否則,i/o管理器將把irp**給驅動提供的例程,該例程將在它所在的裝置層發起i/o操作。

6:當裝置中斷發生時,驅動的中斷服務例程(isr)必須遮蔽相應中斷並儲存相關的上下文環境。然後,isr將呼叫i/o支援例程(iorequestdpc)將該irp傳遞給由本層驅動提供的延時處理呼叫(dpc)例程中,以此使得該操作請求在比isr低一級的硬體優先順序下完成。

7:當驅動程式的dpc執行時,它使用上下文(由isr中呼叫iorequestdpc時傳遞下來)來完成i/o操作。 dpc呼叫相關的例程將下乙個irp(如果有的話)移出佇列並將該irp**給由驅動提供的例程,這個例程開始在這個裝置執行i/o操作。然後,dpc設定irp中的i/o狀態並呼叫例程iocompleterequest將它返回給i/o管理器。

8:i/o管理器把最底層的驅動程式的i/o stack location置零,然後呼叫檔案系統已經註冊好的完成例程(見步驟3)並把分配給fsd的irp傳遞給檔案系統驅動。該完成例程根據i/o狀態(i/o status block)的結果來決定是重發該請求,還是更新原始請求儲存的的內部狀態資訊,或者是釋放分配給驅動的irp。檔案系統收集完所有分配給驅動的irp中的狀態資訊,由此可以設定i/o的狀態資訊並結束原始irp,當檔案系統完成原始的irp時,i/o管理器返回乙個ntstatus的值給發起該i/o操作的原始請求者(子系統的原生函式)。

和上圖描述的檔案系統驅動一樣,任何乙個新增進驅動鏈表的新的驅動程式都可以實現下列功能:

●     在irp中設定自己的完成例程。iocompletion例程檢查i/o status block來判斷該irp是被下一層的驅動成功完成了,還是被取消了, 或者是完成了但有錯誤. 完成例程還可以更新任何由驅動程式儲存的irp相關的狀態, 也可以釋放由驅動分配的任何操作相關的資源。另外,結束irp之前,完成例程還可以延遲irp的完成(通過告訴i/o管理器該irp需要處理更多東西),並且可以在允許該irp完成之前,向下一層驅動程式傳送另外的請求。

●     在分配的irp中可以建立下一層驅動對應的i/o stack location,並將請求傳送給下一層驅動。

●     任何收到的irp都可以通過在每乙個irp中新增針對下一層驅動的i/o stack location並呼叫iocalldriver例程實現**(值得注意的是: 針對主要功能**為irp_mj_power,的irp,驅動必須呼叫pocalldriver例程才能**)。

從上圖我們可以知道,大部分驅動處理irp是通過驅動提供的一組標準例程,但是處在驅動鏈中不同層的驅動必須有不同標準的例程。比如說,只有最底層的驅動可以處理來自物理裝置的中斷,所以只有最底層的驅動可以有isr和dpc,isr和dpc負責完成那些由中斷驅動的i/o操作。從另一方面來說,因為最底層的驅動在收到來自裝置的中斷時就知道這些i/o操作已經完成,所以只有高層的驅動才有乙個或者多個類似上文中提到的fsd的完成例程。

IRP的超時處理

exe部分 include include include include ioctl.h int main void dword dwread 如果讀irp沒有被完成,readfile一直都不會退出 readfile hdevice,null,null,dwread,null printf 第乙個...

對自己裝置的控制IRP的處理

ursaemin ris 10977789 21 20 23 這個irp是deviceiocontrol發下來的,我只返回了status,但是沒skip也沒complete。楚天樂 285008395 21 25 35 deviceiocontrol 楚天樂 285008395 21 25 40 是...

IRP派遣操作

irptrace工具跟蹤irp 派遣函式 dispathc funtion 是windows驅動中的重要概念。驅動程式的主要功能是負責處理i o請求,其中大部分i o請求是在派遣函式中處理的。使用者模式下所有對驅動程式的i o請求。全部由作業系統轉化為乙個叫做irp的資料結構,不同的irp資料會派遣...