使用緩衝 I/O
服務互動式或緩慢裝置的驅動程式,或通常一次傳輸相對少量資料的驅動程式,應該使用 緩衝的 I/O 傳輸方法。 針對小型互動式傳輸使用緩衝 I/O 可改善整體實體記憶體使用量,因為記憶體管理員不需要鎖定每個傳輸的完整實體頁面,如同要求直接 I/O 的驅動程式一樣。 一般而言,視訊、鍵盤、滑鼠、序列和平行驅動程式要求緩衝的 I/O。
I/O 管理員會判斷 I/O 作業使用緩衝 I/O,如下所示:
針對IRP_MJ_READ和IRP_MJ_WRITE要求,DO_BUFFERED_IO是在DEVICE_OBJECT結構的Flags成員中設定。 如需詳細資訊,請參閱 初始化裝置物件。
對於 IRP_MJ_DEVICE_CONTROL 和 IRP_MJ_INTERNAL_DEVICE_CONTROL 要求,IOCTL 程式碼的值會包含 METHOD_BUFFERED 做為 IOCTL 值中的 TransferType 值。 如需詳細資訊,請參閱 定義 I/O 控制程式碼。
下圖說明 I/O 管理員如何為使用緩衝 I/O 的傳輸作業設定 IRP_MJ_READ 要求。
此圖顯示驅動程式如何使用 IRP 中的 SystemBuffer 指標來傳輸讀取要求的資料的概觀,當驅動程式具有 ORed 裝置物件的 旗 標與 DO_BUFFERED_IO:
某些使用者空間虛擬位址範圍代表目前線程的緩衝區,而且該緩衝區的內容可能會儲存在頁面型實體位址範圍內, (上圖中的深色網底) 。
I/O 管理員會服務目前線程的讀取要求,其中線程會傳遞代表緩衝區的使用者空間虛擬位址範圍。
I/O 管理員會檢查使用者提供的緩衝區是否有協助工具,並呼叫 ExAllocatePoolWithTag 來建立非分頁的系統空間緩衝區, (SystemBuffer) 使用者提供的緩衝區大小。
I/O 管理員可在它傳送給驅動程式的 IRP 中,存取新配置的 SystemBuffer 。
如果圖表顯示寫入要求,I/O 管理員會在將 IRP 傳送至驅動程式之前,先將資料從使用者緩衝區複製到系統緩衝區。
針對上圖所示的讀取要求,驅動程式會將裝置的資料讀取到系統空間緩衝區。 此緩衝區的記憶體是非分頁的,而且驅動程式可以安全地存取緩衝區,而不需要先加以鎖定。 滿足讀取要求後,驅動程式會使用 IRP 呼叫 IoCompleteRequest 。
當原始執行緒再次使用中時,I/O 管理員會將系統緩衝區的讀取資料複製到使用者緩衝區。 它也會呼叫 ExFreePool 來釋放系統緩衝區。
在 I/O 管理員為驅動程式建立系統空間緩衝區之後,可以交換要求的使用者模式執行緒,而且可由另一個執行緒重複使用其實體記憶體,可能是由屬於另一個進程的執行緒重複使用。 不過,在驅動程式使用 IRP 呼叫 IoCompleteRequest 之前,IRP 中提供的系統空間虛擬位址範圍仍有效。
一次傳輸大量資料的驅動程式,特別是執行多頁傳輸的驅動程式,不應該嘗試使用緩衝的 I/O。 當系統執行時,非分頁集區可能會變成分散,讓 I/O 管理員無法配置大型、連續的系統空間緩衝區,以在 IRP 中傳送給這類驅動程式。
一般而言,驅動程式會針對某些類型的 IRP 使用緩衝 I/O,例如 IRP_MJ_DEVICE_CONTROL 要求,即使它也使用 直接 I/O也一樣。 使用直接 I/O 的驅動程式通常只會針對 IRP_MJ_READ 和 IRP_MJ_WRITE 要求執行此動作,以及可能需要大量資料傳輸的驅動程式定義 IRP_MJ_INTERNAL_DEVICE_CONTROL 要求。
每個 IRP_MJ_DEVICE_CONTROL 和 IRP_MJ_INTERNAL_DEVICE_CONTROL 要求都包含 I/O 控制項程式碼。 如果 I/O 控制項程式碼指出必須使用緩衝 I/O 來支援 IRP,I/O 管理員會使用單一系統緩衝區來代表使用者應用程式的輸入和輸出緩衝區。 支援這類 I/O 控制程式碼的驅動程式必須讀取輸入資料,如果緩衝區有任何) (,則藉由覆寫輸入資料, () 輸出資料 (。 如需詳細資訊,請參閱 定義 I/O 控制程式碼。