共用方式為


存取 UMDF 1.x 驅動程式中的資料緩衝區

警告

UMDF 2 是最新版的 UMDF,並取代 UMDF 1。 所有新的 UMDF 驅動程式都應該使用 UMDF 2 來撰寫。 未將新功能新增至 UMDF 1,而且較新版本的 Windows 10 上不支援 UMDF 1。 通用 Windows 驅動程式必須使用 UMDF 2。

如需詳細資訊,請參閱使用 UMDF 消費者入門

如需存取 UMDF 2 資料緩衝區的相關資訊,請參閱 存取 WDF 驅動程式中的資料緩衝區

當驅動程式收到讀取、寫入或裝置 I/O 控制要求時,要求物件會包含輸入緩衝區或輸出緩衝區,或兩者。 (一些裝置 I/O 控制要求提供兩個輸入、兩個輸出或兩個輸入/輸出緩衝區。)

輸入緩衝區包含驅動程式所需的資訊。 針對寫入要求,這項資訊通常是函式驅動程式必須傳送至裝置的資料。 針對裝置 I/O 控制要求,輸入緩衝區可能包含資訊,指出驅動程式必須執行的作業類型。

輸出緩衝區會從驅動程式接收資訊。 針對讀取要求,這項資訊通常是函式驅動程式從裝置接收的資料。 針對裝置 I/O 控制要求,輸出緩衝區可能會收到所指定要求之 I/O 控制程式碼的狀態或其他資訊。

驅動程式用來存取要求資料緩衝區的技術,取決於驅動程式用來存取裝置資料緩衝區的方法。 UMDF 支援下列緩衝區存取方法:

第三個存取方法 稱為「未緩衝」或「直接 I/O」,無法供 UMDF 型驅動程式使用,但 UMDF 可以將某些 I/O 要求從 「noter」 方法轉換成 UMDF 版本支援的方法。

在大部分情況下,UMDF 型驅動程式會呼叫相同的 UMDF 物件方法來存取資料緩衝區,不論 UMDF 和驅動程式是使用緩衝 I/O 還是直接 I/O。 直接 I/O 通常提供比緩衝區 I/O 提供的更佳效能。

本主題的下列各節說明:

指定慣用緩衝區存取方法

UMDF 1.9 版和更新版本同時支援緩衝和直接 I/O 存取方法。 驅動程式可以藉由呼叫 IWDFDeviceInitialize2::SetIoTypePreference 來呼叫 IWDFDeviceInitialize2::SetIoTypePreference ,以指定您偏好用於所有裝置讀取、寫入和裝置 I/O 控制要求的存取方法,再呼叫 IWDFDriver::CreateDevice 來建立裝置物件。 例如,如果驅動程式只針對其中一個裝置的讀取和寫入要求指定緩衝 I/O 方法的喜好設定, 則 UMDF 驅動程式主機進程會在將 讀取和寫入要求傳遞給該裝置的驅動程式時,使用緩衝的 I/O 方法。 如果驅動程式指定直接 I/O 的喜好設定,UMDF 可以 (,但可能無法) 使用直接 I/O。 如需 UMDF 何時使用直接 I/O 的詳細資訊,請參閱 UMDF 如何為 I/O 要求選擇緩衝區存取方法

針對驅動程式支援的每個裝置,驅動程式可以針對緩衝 I/O、直接 I/O 或裝置的緩衝或直接 I/O 指定喜好設定。 驅動程式可以針對讀取和寫入要求指定一種類型的存取方法,並為裝置 I/O 控制要求指定另一種類型的存取方法。 如果驅動程式未指定存取方法喜好設定,UMDF 會使用緩衝方法。

針對裝置 I/O 控制要求,IOCTL (IOCTL) 的 I/O 控制程式碼會指定緩衝區存取方法。 (如需 IOCTLs 如何指定存取方法的詳細資訊,請參閱 定義 I/O 控制代碼.) 不過,UMDF 使用的存取方法可能與 IOCTL 指定的存取方法不符。

指定緩衝區擷取模式

在 1.9 版之前的 UMDF 版本中,UMDF 一律會在 UMDF 收到 I/O 要求時,將緩衝區複製到 UMDF 驅動程式主機) 進程 ,讓驅動程式 (使用 I/O 要求。 這個緩衝區擷取模式稱為 立即擷取。 如果發生失敗,UMDF 會以失敗狀態值完成 I/O 要求,且不會將 I/O 要求傳遞給驅動程式。

UMDF 1.9 版和更新版本同時支援立即擷取和 延遲擷取 模式。 延後擷取模式會延後將 I/O 要求的緩衝區複製到驅動程式主機進程,直到驅動程式嘗試存取緩衝區為止。 如果發生失敗,緩衝區存取函式會將錯誤狀態值傳回給驅動程式。

當驅動程式為每個裝置呼叫 IWDFDeviceInitialize2::SetIoTypePreference 時,可以指定緩衝區擷取模式。 使用下列規則:

  • 如果您的驅動程式指定直接 I/O 存取方法,它也必須指定延後擷取模式。 直接 I/O 僅適用于延遲擷取。

  • 所有以 UMDF 1.9 版和更新版本一起執行的驅動程式都應該為所有 I/O 要求指定延遲擷取模式,不論驅動程式選擇緩衝或直接 I/O 存取方法。 延遲擷取可提供較佳的效能,因為它不會存取驅動程式未使用的緩衝區。

如果您的驅動程式未指定緩衝區擷取模式,UMDF 會使用立即擷取。

驅動程式堆疊中的所有 UMDF 驅動程式都必須使用相同的擷取模式。 如果某些驅動程式指定立即擷取,有些則指定延後擷取,UMDF 會使用立即擷取。

UMDF 如何為 I/O 要求選擇緩衝區存取方法

驅動程式呼叫 IWDFDeviceInitialize2::SetIoTypePreference時所指定的存取方法,可能不是 UMDF 所使用的存取方法。 UMDF 會使用下列規則來判斷要使用的存取方法:

  • 驅動程式堆疊中的所有 UMDF 驅動程式都必須使用相同的方法來存取裝置的緩衝區。 如果 UMDF 判斷某些驅動程式偏好緩衝 I/O 或裝置的直接 I/O,而其他驅動程式則只偏好裝置的緩衝 I/O,則 UMDF 會針對所有驅動程式使用緩衝 I/O。 如果一或多個堆疊的驅動程式只偏好緩衝的 I/O,而其他人則只偏好直接 I/O,UMDF 會將事件記錄至系統事件記錄檔,而不會啟動驅動程式堆疊。

    您的驅動程式可以呼叫 IWDFDevice2::GetDeviceStackIoTypePreference ,以判斷 UMDF 已指派給裝置讀取/寫入要求和 I/O 控制要求的緩衝區存取方法。

  • 在某些情況下,驅動程式會在呼叫 IWDFDeviceInitialize2::SetIoTypePreference時指定直接 I/O 的喜好設定,但為了達到最佳效能,UMDF 會針對一或多個裝置的要求使用緩衝 I/O。 例如,如果 UMDF 可以將資料複製到驅動程式緩衝區的速度比對應緩衝區來直接存取,則 UMDF 會針對小型緩衝區使用緩衝 I/O。

    您可以選擇性地設定架構用來判斷架構將使用直接 I/O 之最小緩衝區大小的REG_DWORD類型 DirectTransferThreshold 登錄值。 一般而言,您不需要提供此登錄值,因為架構會使用提供最佳效能的值。 DirectTransferThreshold值位於裝置的[裝置參數\WUDF] 子機碼下,其位於裝置的硬體金鑰底下。

    架構會使用下列規則,根據您在 DirectTransferThreshold中提供的值來判斷臨界值。 所提供的數位假設 PAGE_SIZE 為 4096,但 Itanium 型系統除外。

    • 如果您將 DirectTransferThreshold 設定為小於或等於 8192 (或 2 * PAGE_SIZE) 的任何值,架構會將閾值設定為 8192。 架構會針對小於 8192 位元組的緩衝區使用緩衝 I/O,而緩衝區的直接 I/O 等於或大於 8192 個位元組。

    • 如果您將 DirectTransferThreshold 設定為大於 8192 的任何值,架構會四捨五入到下一個確切的 PAGE_SIZE倍數。 同樣地,架構會針對小於閾值的緩衝區使用緩衝 I/O,而緩衝區的直接 I/O 等於或大於臨界值。

  • UMDF 只會針對在記憶體頁面界限上開始和結束的緩衝區空間使用直接 I/O。 如果緩衝區的開頭或結尾不在頁面界限上,則 UMDF 會針對緩衝區的該部分使用緩衝 I/O。 換句話說,UMDF 可能會針對由數個 I/O 要求組成的大型資料傳輸使用緩衝 I/O 和直接 I/O。

  • 針對裝置 I/O 控制要求,只有在 I/O 控制程式碼 (IOCTL) 指定直接 I/O 時,UMDF 才會使用直接 I/O,而且只有在所有裝置的 UMDF 驅動程式都呼叫 IWDFDeviceInitialize2::SetIoTypePreference 以指定直接存取方法時。

驅動程式會使用相同的要求物件方法來存取資料緩衝區,而不論緩衝區存取方法為何。 因此,大部分驅動程式通常不需要知道 UMDF 是針對 I/O 要求使用緩衝 I/O 還是直接 I/O。

驅動程式如何取得 I/O 要求的存取方法

在某些情況下,如果已知存取方法,您可以改善裝置和驅動程式的效能。 在這種情況下,您的驅動程式可以呼叫 IWDFIoRequest2::GetEffectiveIoType 來取得 I/O 要求的緩衝區存取方法。

例如,請考慮通常會使用直接 I/O 的高輸送量裝置。 因為它使用直接 I/O,所以驅動程式必須在驗證參數之前,先將應用程式指定的參數複製到本機驅動程式記憶體,以確保應用程式不會在驗證之後修改參數。

因為驅動程式偶爾會收到使用緩衝 I/O 的緩衝區,而且因為已複製緩衝的 I/O 緩衝區,所以應用程式無法修改資料,而且驅動程式不需要在驗證參數之前先複製參數。 因此,驅動程式應該檢查每個要求的緩衝區存取方法,以判斷它是否必須在驗證參數之前複製參數。

在 UMDF 驅動程式中使用緩衝 I/O

如果您的驅動程式使用緩衝 I/O,則 UMDF 行為會根據要求類型而有所不同。 針對讀取和寫入要求,驅動程式主機進程會建立驅動程式可以存取的單一中繼緩衝區。

針對寫入要求,驅動程式主機進程會在呼叫驅動程式堆疊之前,先從呼叫應用程式的輸入緩衝區傳輸輸入資訊。 驅動程式通常會從中繼緩衝區讀取輸入資訊,並將它寫入裝置。

針對讀取要求,驅動程式通常會從裝置讀取資訊,並將其儲存在中繼緩衝區中。 驅動程式主機進程會將輸出資料從中繼緩衝區複製到應用程式的輸出緩衝區。

不過,對於裝置 I/O 控制要求,驅動程式主機進程會建立兩個不同的緩衝區,供驅動程式存取。 請注意,這與 WDM 和 KMDF 驅動程式的行為不同,其中讀取、寫入和裝置 I/O 控制要求使用緩衝處理 I/O 傳送,會導致驅動程式存取單一中繼緩衝區。 在此情況下,輸出緩衝區一開始不包含任何內容,而且驅動程式不應該從中讀取。 此外,驅動程式寫入輸入緩衝區的任何資料都會被捨棄,而不會傳回給呼叫的應用程式。

如需何時選擇緩衝 I/O 的指導方針,請參閱 WDF_DEVICE_IO_TYPE

UMDF 1.9 版和更新版本可以支援立即或延後擷取要求緩衝區。 如需詳細資訊,請參閱 WDF_DEVICE_IO_BUFFER_RETRIEVAL

使用立即緩衝區擷取模式的驅動程式必須使用 IWDFIoRequest::GetInputMemoryIWDFIoRequest::GetOutputMemory 來存取緩衝區。

使用延後緩衝區擷取模式的驅動程式可以呼叫 IWDFIoRequest2::RetrieveInputBufferIWDFIoRequest2::RetrieveInputMemoryIWDFIoRequest2::RetrieveOutputBufferIWDFIoRequest2::RetrieveOutputMemory來存取緩衝區。

在 UMDF 驅動程式中使用直接 I/O

如果您的驅動程式使用直接 I/O,驅動程式主機進程會驗證緩衝區空間的存取範圍,該緩衝區空間的起始者通常 (使用者模式應用程式) 指定、將緩衝區空間鎖定為實體記憶體,然後提供驅動程式直接存取緩衝區空間。

如需何時選擇直接 I/O 的指導方針,請參閱 WDF_DEVICE_IO_TYPE

驅動程式可以呼叫 IWDFIoRequest2::RetrieveInputBufferIWDFIoRequest2::RetrieveInputMemoryIWDFIoRequest2::RetrieveOutputBufferIWDFIoRequest2::RetrieveOutputMemory來存取緩衝區。

在 UMDF 驅動程式中使用未緩衝的 I/O 或直接 I/O

稱為 「緩衝 I/O」或直接 I/O 方法 的緩衝區存取方法 (或簡短的「不」方法) 可讓驅動程式直接存取應用程式的要求緩衝區指標。 UMDF 型驅動程式無法使用這個存取方法。

不過,某些裝置 I/O 控制代碼 的定義 (IOCTLs) 指定要求使用「兩者」方法。 或者,UMDF 可以將這類裝置 I/O 控制要求的緩衝區存取方法轉換為緩衝 I/O 或直接 I/O。 使用下列步驟:

  1. UmdfMethodNeitherAction 指示詞包含在驅動程式 INF 檔案的 INF DDInstall 區段中 。 您可以設定 指示詞的值,指出 UMDF 應該將使用「兩者」存取方法的裝置 I/O 控制要求傳遞給驅動程式。 (否則,UMDF 會以錯誤狀態值完成這些 I/O 要求。)

  2. 使用 UMDF 針對 緩衝 I/O直接 I/O提供的物件方法,存取 I/O 要求的緩衝區。

只有在您確定 UMDF 可以將存取方法轉換成緩衝 I/O 或直接 I/O 時,才應該啟用 IOCTL 要求的支援。 例如,如果 IOCTL 指定未遵循緩衝區規格規則的自訂要求,則 I /O 控制代碼的緩衝區描述中所述,UMDF 無法轉換緩衝區。