共用方式為


DMA 驗證

DMA 驗證會監視直接記憶體存取 (DMA) 的使用。 由於 DMA 常式已隨著 Windows 的發展而變更,因此許多驅動程式會不正確地使用 DMA 呼叫。 此外,部分驅動程式寫入器會嘗試完全略過 HAL DMA 子系統。 這種做法可能會將陰險的錯誤引入驅動程式。

驅動程式驗證器的 DMA 驗證選項會嘗試攔截常見的 DMA 錯誤。 與 !dma 核心偵錯工具延伸模組一起,可用來確認驅動程式是否以適當的方式使用 DMA。

此驅動程式驗證器選項也稱為 HAL 驗證。 驅動程式驗證器所產生的某些錯誤訊息可能會使用此術語。

不同類型的 DMA

DMA 是一種機制,透過該機制,硬體設備可以在不使用處理器的情況下將資料傳輸到記憶體或從記憶體傳輸資料。 需要處理器來設定傳輸,裝置會在完成傳輸時向處理器發出訊號。 此系統的優點是處理器可以在執行 DMA 傳輸時執行其他工作。

Windows 2000 和更新版本中使用數種類型的 DMA:

通用緩衝區 DMA
當系統可以配置硬體和軟體都可以存取的單一緩衝區時,就會執行通用緩衝區 DMA。 驅動程式負責同步處理緩衝區的存取。 記憶體不會快取,讓驅動程式更容易進行同步處理。 設定通用緩衝區之後,驅動程式和硬體都可以直接寫入緩衝區中的位址,而不需要 HAL 的任何介入。

封包 DMA
當有單一現有緩衝區必須對應以供硬體使用時,會執行封包 DMA。 使用封包 DMA 的範例是將檔案從記憶體傳輸到磁碟。 在此情況下使用通用緩衝區 DMA 會很浪費,因為必須先將檔案傳輸至通用緩衝區,硬體才能將檔案傳輸至磁碟。 相反,會先諮詢 HAL,然後由它提供訊息給驅動程式,以協助硬體在記憶體中尋找實際的緩衝區。 由於需要涉及的例程跨不同架構工作,因此此操作變得複雜。

分散/收集 DMA
分散/收集 DMA 是一種快捷方式,可一次設定多個封包 DMA 傳輸。 例如,如果您要透過網路傳輸封包,則網路堆疊的每個部分都會新增自己的標頭 (TCP、IP、乙太網路等)。 這些標頭都是從記憶體中的不同位置配置的。 在這種情況下,分散/收集 DMA 會向 HAL 發出批次要求,將每個標頭和資料區段對應,以供硬體存取,從而節省時間。 這個方法不需要在封包的每個部分呼叫封包 DMA 常式,而是呼叫每個常式一次,並讓 HAL 負責個別對應每個常式。

注意分散/收集功能 並不表示裝置可以使用分散/收集常式。 分散/收集功能是指裝置描述中的旗標,指出裝置能夠從記憶體中的任何區域讀取或寫入,而不僅僅是特定範圍。

系統DMA
系統DMA是透過對主機板上的系統DMA控制器進行編程,直接進行傳輸來執行的。 只有 ISA 卡可以使用系統 DMA。

DMA 驗證的影響

當 DMA 驗證處於作用中狀態時,驅動程式驗證器會偵測 DMA 常式的誤用,包括:

  • DMA 記憶體緩衝區的溢位或欠載(這些錯誤可能由硬體或驅動程式產生)。

  • 雙重釋放共用緩衝區、配接卡通道、對應暫存器或散佈/收集清單。

  • 透過不釋放常用緩衝區、配接器通道、映射暫存器、散佈/集結清單或配接器來流失記憶體。

  • 同時為一個適配器提供多於一個的通道。

  • 嘗試使用已釋放且不再存在的轉接器。

  • 未排清配接器緩衝區。

  • 適配器的未結清的參照計數過多。

  • 在可分頁緩衝區上執行 DMA (在 DMA 傳輸開始之前,所有緩衝區都應該鎖定) 。

  • 在具有損毀旗標的 MDL 上執行 DMA。

  • 在參照無效的系統位址時,有幾種情況可能發生:在第一個 MDL 之前,第一個 MDL 結束之後,或者使用比 MDL 緩衝區更長且跨越 MDL 內頁面界限的傳輸長度。

  • 一次配置太多對映暫存器,或配置的對映暫存器超過容許的數目上限。

  • 地圖暫存器的重複映射。

  • 嘗試釋放映射暫存器,而有些暫存器仍在映射中。

  • 嘗試排清尚未被映射的映射暫存器。

  • 嘗試在對應暫存器檔案結尾排清太多位元組。

  • 在不正確的 IRQL 呼叫 DMA 常式。

  • 將空值DMA_ADAPTER傳遞至 HAL 常式。

  • 當地址和 MDL 未包含在 MDL 中時,將地址和 MDL 傳遞給 HAL 常式。

  • 嘗試對應已對應的位址範圍。

  • 嘗試排清未對應的緩衝區。

  • 嘗試映射零長度緩衝區以進行傳輸。

  • 呼叫過時的函式 HalGetAdapter (所有驅動程式都必須改用 IoGetDmaAdapter ) 。

驅動程式驗證器會監控驅動程式的行為,如果發生任何違規,將進行錯誤檢查0xE6。 如需查看錯誤檢查參數的清單,請參閱 Bug Check 0xE6(DRIVER_VERIFIER_DMA_VIOLATION)。

DMA 驗證什麼時候有用?

所有直接使用 DMA (呼叫 HAL DMA 常式) 的驅動程式都應使用 DMA 驗證進行測試。

此外,也應該測試迷你埠驅動程式,因為它們通常會間接使用 DMA (呼叫使用 DMA 的埠驅動程式) 。

DMA 驗證也是偵測記憶體損毀的有效方式,因為它可以發現驅動程式或硬體裝置何時滿溢 DMA 緩衝區。

監控 DMA 驗證

核心偵錯工具延伸模組 !dma 可用來顯示豐富的 DMA 資訊。 它可以顯示每個 DMA 配接器行為的各種詳細數據。 在適用於 Windows 的偵錯工具套件中的檔中,有 !dma 延伸模組的詳細範例,以及偵錯工具延伸模組的一般資訊。 如需詳細資訊,請參閱 Windows 偵錯

啟用此選項

您可以使用驅動程式驗證器管理員或 Verifier.exe 命令列來啟用一或多個驅動程式的 DMA 驗證功能。 如需詳細資訊,請參閱 選取驅動程式驗證器選項

  • 在命令行

    在命令列中,DMA 驗證選項由 位 7 (0x80) 表示。 若要啟用 DMA 驗證,請使用 0x80 的旗標值,或將0x80新增至旗標值。 例如:

    verifier /flags 0x80 /driver MyDriver.sys
    

    下一次開機之後,此功能將會處於作用中狀態。

    在 Windows Vista 和更新版本的 Windows 上,您也可以將 /volatile 參數新增至命令,以啟用和停用 DMA 驗證,而不需要重新啟動電腦。 例如:

    verifier /volatile /flags 0x80 /adddriver MyDriver.sys
    

    此設定會立即生效,但會在您關閉或重新啟動電腦時遺失。 如需詳細資訊,請參閱 使用動態設定

    標準設定中也包含 DMA 驗證功能。 例如:

    verifier /standard /driver MyDriver.sys
    
  • 使用驅動程式驗證器管理員

    1. 啟動驅動程式驗證器管理員。 在命令提示字元視窗中輸入 驗證程式
    2. 選取 [建立自定義設定] (適用於程式代碼開發人員), 然後按 [ 下一步]。
    3. 選擇 從完整清單中選取個別設定
    4. 選取 (核取) DMA 驗證

    標準設定中也包含 DMA 驗證功能。 若要使用此功能,請在 [驅動程序驗證器管理員] 中,按兩下 [建立標準設定]。