範例 I/O 要求 - 詳細數據

說明開啟檔案物件的圖表會顯示具有兩個 I/O 堆棧位置的 IRP,但 IRP 可以有任意數目的 I/O 堆疊位置,視有多少分層驅動程式會處理指定的要求而定。

下圖詳細說明 開啟檔案物件 圖中的驅動程式如何使用 I/O 支援例程 (IoXxx 例程) 來處理讀取或寫入要求的 IRP。

說明在分層驅動程序中處理 irps 的圖表。

  1. I/O 管理員會呼叫文件系統驅動程式 (FSD) ,並使用它為子系統的讀取/寫入要求配置的 IRP。 FSD 會在 IRP 中存取其 I/O 堆疊位置,以判斷它應該執行的作業。

  2. FSD 可以藉由呼叫 I/O 支援例程 (IoAllocateIrp) 一或多次來配置額外的 IRP,將原始要求分成較小的要求, (多個設備驅動器) 。 針對較低層級驅動程式 () ,額外的 I/O 堆疊位置會傳回至具有零填滿 I/O 堆疊位置 (的 FSD) 。 FSD 可以自行重複使用原始 IRP,而不是配置上圖所示的其他 IRP,方法是在原始 IRP 中設定下一個較低驅動程式的 I/O 堆棧位置,並將它傳遞至較低的驅動程式。

  3. 針對每個驅動程式配置的 IRP,上圖中的 FSD 會呼叫 I/O 支援例程來註冊 FSD 提供的完成例程;在完成例程中,FSD 可以判斷較低驅動程式是否符合要求,而且可以在較低驅動程式完成時釋放每個驅動程式配置的 IRP。 I/O 管理員會呼叫 FSD 提供的完成例程,不論每個驅動程式配置的 IRP 都已順利完成、完成並出現錯誤狀態,還是已取消。 較高層級的驅動程式負責釋放它所配置的任何 IRP,並代表較低層級的驅動程式自行設定。 I/O 管理員會在所有驅動程式完成它們之後釋出其配置的 IRP。

    接下來,FSD 會呼叫 I/O 支援例程 (IoGetNextIrpStackLocation) ,以存取下一個較低層級驅動程式的 I/O 堆棧位置,以設定下一個較低層級驅動程式的要求。 (在上圖中,下一個較低的驅動程式會是最低層級的驅動程式。) FSD 接著會呼叫 I/O 支援例程, (IoCallDriver) 將該 IRP 傳遞給下一個較低的驅動程式。

  4. 使用 IRP 呼叫時,最低層級驅動程式會檢查其 I/O 堆疊位置,以判斷IRP_MJ_XXX 函式程式代碼所指出的作業 (,) 應該在目標裝置上執行。 目標裝置是由裝置物件在其指定的 I/O 堆疊位置中表示,並以 IRP 傳遞至驅動程式。 最低層級驅動程式可以假設 I/O 管理員已將 IRP 路由傳送至針對 IRP_MJ_XXX 作業定義的驅動程式進入點, (此處IRP_MJ_READIRP_MJ_WRITE) ,且較高層級驅動程式已檢查要求的其他參數有效性。

    如果沒有較高層級的驅動程式,最低層級驅動程式會檢查 IRP_MJ_XXX 作業的輸入參數是否有效。 如果是,驅動程式通常會呼叫 I/O 支援例程,告知 I/O 管理員裝置作業擱置在 IRP 上,並將它傳遞給另一個驅動程式提供的例程,以存取目標裝置 (此處、實體或邏輯裝置:磁碟或磁碟上的磁碟分區) 。

  5. I/O 管理員會判斷驅動程式是否已忙於處理目標裝置的另一個 IRP、將 IRP 排入佇列,然後傳回。 否則,I/O 管理員會將 IRP 路由傳送至驅動程式提供的例程,以在其裝置上啟動 I/O 作業。 (在這個階段中,上圖中的驅動程式和 I/O 管理員傳回 control.)

  6. 當裝置中斷時,驅動程式的中斷服務例程 (ISR) 只會執行許多工作,因為它必須停止裝置中斷,並儲存與作業有關的必要內容。 ISR 接著會呼叫 I/O 支援例程, (IoRequestDpc) IRP,將驅動程式提供的 DPC (延後過程調用排入佇列,) 例程,以比 ISR 低的硬體優先順序完成要求的作業。

  7. 當驅動程式的 DPC 取得控制權時,它會使用在 ISR 呼叫 IoRequestDpc 中傳遞的內容 () 來完成 I/O 作業。 如果有任何) ,並將該 IRP 傳遞給啟動裝置上 I/O 作業的驅動程式提供的例程 (,DPC 會呼叫支援例程來清除下一個 IRP (,請參閱步驟 5) 。 DPC 接著會在 IRP 的 I/O 狀態區塊中設定剛完成作業的狀態,並使用 IoCompleteRequest 將它傳回給 I/O 管理員。

  8. I/O 管理員會將 IRP 中最低層級驅動程式的 I/O 堆疊位置零,並呼叫文件系統的已註冊完成例程 (請參閱 FSD 配置的 IRP 的步驟 3) 。 此完成例程會檢查 I/O 狀態區塊,以判斷是否要重試要求,或更新與原始要求相關的任何內部狀態,以及釋放其驅動程式配置的 IRP。 檔系統可以收集它傳送至較低層級驅動程式的所有驅動程式配置 IRP 的狀態資訊,以便設定 I/O 狀態並完成原始 IRP。 當文件系統完成原始 IRP 時,I/O 管理員會將 和 NTSTATUS 值傳回原始要求者, (子系統的 I/O 作業原生函式) 。

如同分層 驅動程式中處理 IRP 圖中顯示的檔案系統驅動程式,任何新增至現有驅動程式鏈結的新驅動程式都可以執行下列所有動作:

  • 將自己的完成例程設定為 IRP。 IoCompletion 例程會檢查 I/O 狀態區塊,以判斷較低驅動程式是否已順利完成 IRP、取消 IRP,以及/或已完成,並出現錯誤。 完成例程也可以更新驅動程式可能已儲存的任何 IRP 特定狀態、釋放驅動程式可能已配置的任何作業特定資源,依此類推,再完成 IRP。 此外,完成例程可以延遲 IRP 完成 (,方法是通知 I/O 管理員 IRP) 需要更多處理,而且可以在允許 IRP 完成之前,將另一個要求傳送至下一個較低層級的驅動程式。

  • 在所配置 IRP 中設定下一個較低層級驅動程式的 I/O 堆疊位置,並將要求傳送至下一個較低層級的驅動程式。

  • 藉由在每個 IRP 中設定下一個較低驅動程式的 I/O 堆疊位置,並呼叫 IoCallDriver,將任何傳入要求傳遞給較低的驅動程式。 (請注意,對於具有主要函式程式代碼 IRP_MJ_POWER的 IRP,驅動程式必須使用 PoCallDriver.)

每個驅動程式建立的裝置物件都代表特定驅動程式執行 I/O 要求的實體、邏輯或虛擬設備。 如需建立和設定裝置對象的詳細資訊,請參閱 裝置物件和裝置堆疊

分層驅動程式中的處理 IRP 圖所示,大部分的驅動程式會透過一組由驅動程式提供的標準 例程,以階段方式處理每個 IRP,但鏈結中不同層級的驅動程式必須有不同的標準例程。 例如,只有最低層級的驅動程式會處理來自實體裝置的中斷,因此只有最低層級的驅動程式會有ISR和 DPC 來完成插斷驅動 I/O 作業。 另一方面,由於這類驅動程式知道 I/O 在收到裝置中斷時已完成,因此不需要完成例程。 只有較高層級的驅動程式會有一或多個完成例程,例如此圖中的 FSD。