共用方式為


使用緩衝 I/O

服務互動式或緩慢裝置的驅動程式,或通常一次傳輸相對少量數據的驅動程式,應該使用 緩衝的 I/O 傳輸方法。 使用緩衝 I/O 進行小型互動式傳輸可改善整體物理記憶體的使用,因為記憶體管理器不需要像使用直接 I/O 的驅動程式一樣,為每個傳輸鎖定整個實體頁面。 一般而言,視訊、鍵盤、滑鼠、序列和平行驅動程式要求緩衝的 I/O。

I/O 管理員會判斷 I/O 作業使用緩衝的 I/O,如下所示:

下圖說明 I/O 管理員如何為使用緩衝 I/O 的傳輸作業設定 IRP_MJ_READ 要求。

圖表說明用戶緩衝區的緩衝 I/O。

此圖顯示驅動程式如何在 IRP 中使用 SystemBuffer 指標來傳輸讀取要求的數據,當驅動程式將裝置物件的 Flags 與 DO_BUFFERED_IO 進行 OR 運算時。

  1. 某些範圍的使用者空間虛擬位址代表目前線程的緩衝區,而該緩衝區的內容可能會儲存在頁面型實體位址範圍內的某處(上圖中的深色底紋)。

  2. I/O 管理員會服務目前線程的讀取要求,其中線程會傳遞代表緩衝區的使用者空間虛擬位址範圍。

  3. I/O 管理員會檢查使用者提供的緩衝區是否可存取,並呼叫 ExAllocatePoolWithTag 來創建一個與使用者提供的緩衝區大小相同的非分頁系統空間緩衝區(SystemBuffer)。

  4. I/O 管理員可在傳送給驅動程式的 IRP 中,存取新配置的 SystemBuffer

    如果此圖顯示寫入要求,I/O 管理員會在將 IRP 傳送至驅動程式之前,先將數據從用戶緩衝區複製到系統緩衝區。

  5. 針對上圖所示的讀取要求,驅動程式會將裝置的數據讀取到系統空間緩衝區。 此緩衝區的記憶體未分頁,而且驅動程式可以安全地存取緩衝區,而不需要先鎖定它。 當讀取要求滿足時,驅動程式會使用 IRP 呼叫 IoCompleteRequest

  6. 當原始線程再次作用中時,I/O 管理員會將讀取數據從系統緩衝區複製到用戶緩衝區。 它也會呼叫 ExFreePool 來釋放系統緩衝區。

在 I/O 管理員為驅動程式建立系統空間緩衝區之後,請求的使用者模式線程可以被置換,其物理記憶體可以由另一個線程重複使用,這個線程可能屬於另一個進程。 不過,IRP 中提供的系統空間虛擬位址範圍會維持有效狀態,直到驅動程式使用 IRP 呼叫 IoCompleteRequest 為止。

一次傳輸大量數據的驅動程式,特別是執行多頁傳輸的驅動程式,不應該嘗試使用緩衝的 I/O。 當系統執行時,非分頁池可能會變得分散,讓 I/O 管理程式無法配置大型、連續的系統空間緩衝區,以在 IRP 中傳送給這類驅動程式。

一般而言,驅動程式會針對某些類型的 IRP 使用緩衝 I/O,例如 IRP_MJ_DEVICE_CONTROL 要求,即使它也使用 直接 I/O。 使用直接 I/O 的驅動程式通常只會針對 IRP_MJ_READIRP_MJ_WRITE 要求執行,以及可能需要大量數據傳輸的驅動程式定義 IRP_MJ_INTERNAL_DEVICE_CONTROL 要求。

每個 IRP_MJ_DEVICE_CONTROLIRP_MJ_INTERNAL_DEVICE_CONTROL 要求都包含 I/O 控制件程式代碼。 如果 I/O 控制項程式代碼指出必須使用緩衝 I/O 來支援 IRP,I/O 管理員會使用單一系統緩衝區來代表使用者應用程式的輸入和輸出緩衝區。 支援這類 I/O 控制項程式碼的驅動程式必須從緩衝區讀取輸入資料(如果有的話),然後覆寫輸入數據來提供輸出資料(如果有的話)。 如需詳細資訊,請參閱 定義 I/O 控制程式碼