處理Intermediate-Level驅動程式中的 IRP
較高層級的驅動程式有一組與最低層級設備磁碟機不同的標準常式,其中兩種驅動程式類型通用的標準常式子集重迭。
中繼和最高層級驅動程式的一組常式也會根據下列準則而有所不同:
基礎實體裝置的本質
基礎設備磁碟機是否設定直接或緩衝 I/O 的裝置物件
個別較高層級驅動程式的設計
下圖說明 IRP 在上一節所述的最低層級設備磁碟機上,分層于某處的中繼 鏡像驅動程式 標準常式的路徑。
下圖所示的驅動程式具有下列特性:
驅動程式會分層在多個實體裝置上,而且可能超過一個以上的設備磁碟機。
根據輸入 IRP 中所要求的作業,驅動程式有時會為較低層級的驅動程式配置額外的 IRP。
驅動程式至少有一個檔案系統驅動程式分層在上面,而且該檔案系統驅動程式可能會分層至高於此驅動程式的其他中繼驅動程式。
如圖所示,I/O 管理員會建立 IRP,並將它傳送至指定的主要函式程式碼的驅動程式分派常式。 假設函式程式碼 IRP_MJ_WRITE,分派常式為 DDDispatchWrite。 中繼驅動程式的 I/O 堆疊位置會顯示在中間,其中顯示較高層級和較低層級驅動程式的 I/O 堆疊位置數目無限期。
配置 IRP
鏡像驅動程式的目的是將寫入要求傳送至數個實體裝置,以及將讀取要求替代傳送給這些裝置的驅動程式。 針對寫入要求,驅動程式會針對要寫入資料的每個裝置建立重複的 IRP,假設輸入 IRP 中的參數有效。
上圖顯示 IoAllocateIrp 的呼叫,但較高層級的驅動程式可以呼叫其他支援常式,以配置較低層級驅動程式的 IRP。 請參閱 建立Lower-Level驅動程式的 IRP。
當分派常式呼叫 IoAllocateIrp時,它會指定 IRP 所需的 I/O 堆疊位置數目。 驅動程式必須指定鏈結中每個較低驅動程式的堆疊位置,從鏡像驅動程式正下方的每個驅動程式裝置物件取得適當的值。 選擇性地,當驅動程式呼叫 IoAllocateIrp 以取得它所配置之每個 IRP 的堆疊位置時,驅動程式可以將一個新增至此值,如同上圖中的驅動程式一樣。
此中繼驅動程式的分派常式會呼叫 IoGetCurrentIrpStackLocation (未顯示原始 IRP) ,以檢查參數。
它會呼叫 IoSetNextIrpStackLocation ,因為它在每個新建立的 IRP 和 IoGetCurrentIrpStackLocation 中配置自己的堆疊位置,以建立它稍後在 IoCompletion 常式中使用的內容。
接下來,它會使用每個新建立的 IRP 呼叫 IoGetNextIrpStackLocation ,以便在配置之 IRP 中設定下一個較低層級驅動程式的 I/O 堆疊位置。 鏡像驅動程式的分派常式會將 IRP 函式代碼和參數 (指標複製到傳輸緩衝區的指標,IRP_MJ_WRITE) 傳送到下一個較低驅動程式的 I /O 堆疊位置。 接著,這些驅動程式會設定驅動程式的 I/O 堆疊位置,如果有的話。
呼叫 IoSetCompletionRoutine 和 IoCallDriver
上圖中的分派常式會針對配置的每個 IRP 呼叫 IoSetCompletionRoutine 。 因為上圖中的驅動程式必須處置它配置的 IRP,所以當較低驅動程式完成 IRP 時,此驅動程式會將其 IoCompletion 常式設定為呼叫,不論 I/O 作業是否成功完成、失敗或已取消。
因為上圖中的驅動程式會平行鏡像,所以它會藉由呼叫 IoCallDriver 兩次,針對代表鏡像分割的每個目標裝置物件,將它配置的兩個 IRP 傳遞至下一個較低層級的驅動程式。
處理驅動程式 IoCompletion 常式中的 IRP
當任一組較低層級的驅動程式完成要求的作業時,I/O 管理員會呼叫中繼鏡像驅動程式的 IoCompletion 常式。 鏡像驅動程式會維護原始 IRP 本身 I/O 堆疊位置中的計數,以追蹤下層驅動程式何時完成所有重複的 IRP。
假設 I/O 狀態欄塊表示一組較低的驅動程式已完成 上圖所示的重複 IRP,鏡像驅動程式 的 IoCompletion 常式會遞減其計數,但必須先將計數遞減為零,否則無法完成原始 IRP。 如果遞減的計數還不是零, IoCompletion 常式會呼叫上圖中第一個傳回的 IRP (DupIRP1 的 IoFreeIrp ,) 驅動程式配置並傳回STATUS_MORE_PROCESSING_REQUIRED。
使用上圖所示的 DupIRP2 再次呼叫鏡像驅動程式 的 IoCompletion 常式時, IoCompletion 常式會遞減原始 IRP 中的計數,並判斷這兩組較低層級驅動程式都已執行要求的作業。
假設 DupIRP2 中的 I/O 狀態欄塊也設定為 STATUS_SUCCESS, IoCompletion 常式會將 I/O 狀態欄塊從 DupIRP2 複製到原始 IRP,並釋放 DupIRP2。 它會使用原始 IRP 呼叫 IoCompleteRequest ,並傳回STATUS_MORE_PROCESSING_REQUIRED。 傳回此狀態可防止 I/O 管理員嘗試在 DupIRP2 上進行任何進一步的完成處理;因為 IRP 與執行緒沒有關聯,所以其完成處理應該以建立它的驅動程式結束。
如果任一組較低層級的驅動程式未順利完成鏡像驅動程式的 IRP,鏡像驅動程式的 IoCompletion 常式應該記錄錯誤並嘗試適當的鏡像資料復原。 如需詳細資訊,請參閱 記錄錯誤。