IRP的傳遞與完成

在Windows分層驅動模型中,設備棧中的設備一般都是通過對上層傳來的IRP做相應的處理來實現驅動的功能。這裏對常用的幾種IRP傳遞及完成的方式進行歸納和總結:

1. 在本層驅動中完成

1.1 在本層驅動中以同步方式完成
在本層同步完成一般做完相應處理後,設置Irp->IoStatus.Status和Irp->IoStatus.Information,調用IoCompleteRequest完成該IRP,return IRP的完成狀態即可。

1.2 在本層驅動中以異步方式完成
在本層異步完成一般是得到IRP後將其入隊/起線程另行處理,同時調用IoMarkIrpPending將該IRP標記爲Pending,之後即可return STATUS_PENDING。此時該IRP並未真正完成,需待未決的操作在他處完成後調用IoCompleteRequest才真正完成。


2. 轉發至下層驅動

2.1 本層不作處理
有時對於某些IRP,本層驅動不需要做任何處理。此時可調用IoSkipCurrentIrpStackLocation跳過當前設備棧,然後調用IoCallDriver將IRP轉發至下層驅動,並將轉發的結果直接返回。此種處理方式並不需要關心下層驅動處理IRP的方式究竟是同步還是異步。IRP轉發至下層後就與己無關了。

2.2 同步轉發方式
有時IRP在本層無法直接處理,需要將其轉發至下層,待下層處理完後在其結果上進行修改再將其返回。這時可以採用同步轉發方式進行處理。首先在相應dispatch routine中初始化一個未激發的event,調用IoCopyCurrentIrpStackLocationToNext將本層設備棧參數複製到下層。然後設置一個CompletionRoutine,將剛纔初始化過的event作爲context傳給它。之後調用IoCallDriver轉發IRP至下層,並判斷返回值是否爲STATUS_PENDING。是則wait之前的event。在CompletionRoutine中判斷該IRP是否PendingReturned,是則說明之前IoCallDriver返回了STATUS_PENDING,於是激發event。CompletionRoutine返回STATUS_MORE_PROCESSING_REQUIRED使我們的dispatch routine重新取得對該IRP的控制權。本層dispatch等待結束再次獲得控制權後,進行相應處理,之後需再次調用IoCompleteRequest完成該IRP。
同步轉發是驅動中常用的一種IRP處理方式。一般會將本層dispatch轉發IRP至下層並等待CompletionRoutine激發event的行爲獨立成一個ForwardIrpSynchronous的函數。幾個dispatch只需一個ForwardIrpSynchronous,代碼相對簡單。
注意不要在本層dispatch中調用IoMarkIrpPending,因爲上層的請求在本層被同步處理了。在同步轉發中,如果下層驅動也採用同步方式處理,則本層dispatch不會(也不需要)wait,IoCallDriver返回時CompletionRoutine已經被調用,性能上也沒有什麼損失。

2.3 異步轉發方式
異步轉發也能在下層驅動完成IRP時獲得處理的機會,其主要是採用了異步處理機制。首先本層dispatch調用IoCopyCurrentIrpStackLocationToNext將本層設備棧參數複製到下層,設置相應的CompletionRoutine,然後調用IoCallDriver將IRP轉發至下層驅動,並將轉發的結果直接return給上層調用者。在CompletionRoutine中再判斷該IRP是否PendingReturned,是則需要調用IoMarkIrpPending。之後可對下層驅動處理該IRP的結果進行相應操作。最後返回STATUS_CONTINUE_COMPLETION(同STATUS_SUCCESS)。
異步轉發在異步處理時性能最佳,但處理的邏輯放在了CompletionRoutine中,因此多個dispatch需要編寫多個CompletionRoutine。而同步轉發往往幾個dispatch只需一個ForwardIrpSynchronous即可,代碼相對簡單。


值得注意的是,各個dispatch routine運行的IRQL是由調用關係決定的。如果上層調用者有運行在DISPATCH_LEVEL的可能,則本層的dispatch也需要按照運行在DISPATCH_LEVEL來設計。比如傳遞至本層dispatch的IRP是在上層驅動的StartIO例程中轉發的,則本層處理該類IRP的代碼就可能運行在DISPATCH_LEVEL。

 轉自:http://www.cnblogs.com/spinsoft/archive/2012/06/26/2563808.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章