讀取和篩選偵錯訊息

DbgPrintExvDbgPrintExvDbgPrintExWithPrefixKdPrintEx常式會在您指定的條件下,將訊息傳送至核心偵錯工具。 此程式可讓您篩選掉低優先順序的訊息。

注意

在 Microsoft Windows Server 2003 和舊版 Windows 中, DbgPrintKdPrint 常式會無條件地將訊息傳送至核心偵錯工具。 在 Windows Vista 和更新版本的 Windows 中,這些常式會有條件地傳送訊息,例如 DbgPrintExKdPrintEx。 無論您使用的 Windows 版本為何,您應該使用DbgPrintEx、vDbgPrintExvDbgPrintExWithPrefixKdPrintEx,因為這些常式可讓您控制訊息傳送的條件。

篩選偵錯訊息

  1. 針對您想要傳送至偵錯工具的每個訊息,請在驅動程式的程式碼中使用DbgPrintExvDbgPrintEx、vDbgPrintExWithPrefixKdPrintEx 將適當的元件名稱傳遞至 ComponentId 參數,並將值傳遞至 Level 參數,以反映此訊息的嚴重性或本質。 訊息本身會使用與 printf相同的語法,傳遞至Format引數參數。

  2. 設定適當 元件篩選遮罩的值。 每個元件都有不同的遮罩。 遮罩值會指出該元件的訊息顯示哪一個。 您可以使用登錄編輯器或在記憶體中使用核心偵錯工具,在登錄中設定元件篩選遮罩。

  3. 將核心偵錯工具附加至電腦。 每當驅動程式將訊息傳遞至DbgPrintEx、vDbgPrintExvDbgPrintExWithPrefixKdPrintEx時,傳遞至ComponentIdLevel的值都會與對應的元件篩選遮罩值進行比較。 如果這些值符合特定準則,訊息會傳送至核心偵錯工具並顯示。 否則,不會傳送任何訊息。

注意

此頁面上 DbgPrintEx 的所有參考都同樣適用于 KdPrintExvDbgPrintExvDbgPrintExWithPrefix

識別元件名稱

每個元件都有個別的篩選遮罩。 這可讓偵錯工具個別設定每個元件的篩選。

每個元件會以不同的方式參考,視內容而定。 在DbgPrintExComponentId參數中,元件名稱前面會加上 「DPFLTR_」,後面加上 「_ID」。 在登錄中,元件篩選遮罩的名稱與元件本身相同。 在偵錯工具中,元件篩選遮罩前面加上 「Kd_」,尾碼為 「_Mask」。

Microsoft Windows Driver Kit (WDK () 標頭 dpfilter.h 中_ID格式) 所有元件名稱的完整清單DPFLTR_XXXX_ID格式。 其中大部分的元件名稱都保留給 Windows 和 Microsoft 所撰寫的驅動程式。

有六個元件名稱保留給獨立硬體廠商。 若要避免將驅動程式的輸出與 Windows 元件的輸出混合,您應該使用下列其中一個元件名稱:

元件名稱 驅動程式類型
IHVVIDEO 視訊驅動程式
IHVAUDIO 音訊驅動程式
IHVNETWORK 網路驅動程式
IHVSTREAMING 核心串流驅動程式
IHVBUS 匯流排驅動程式
IHVDRIVER 任何其他類型的驅動程式

例如,如果您要撰寫視訊驅動程式,您會使用 DPFLTR_IHVVIDEO_ID 作為DbgPrintExComponentId參數、在登錄中使用值名稱IHVVIDEO,並在偵錯工具中參考Kd_IHVVIDEO_Mask

DbgPrintKdPrint所傳送的所有訊息都會與DEFAULT元件相關聯。

選擇正確的層級

DbgPrintEx常式的Level參數的類型為 DWORD。 它用來判斷 重要性位欄位Level參數與這個位欄位之間的連線取決於Level的大小:

  • 如果 Level 等於介於 0 到 31 之間的數位,則它會解譯為位移位。 重要性位欄位會設定為值 1 <<Level。 因此,針對 Level 選擇介於 0 到 31 之間的值會導致位欄位只設定一個位。 如果 Level 為 0,則位欄位相當於0x00000001;如果 Level 為 31,則位欄位相當於0x80000000。

  • 如果 Level 是介於 32 和0xFFFFFFFF之間的數位,則重要性位欄位會設定為 Level 本身的值。

因此,如果您想要將位欄位設定為 0x00004000,您可以將 Level 指定為 0x00004000,或直接指定為 14。 請注意,此系統無法提供特定位域值,包括完全零的位欄位。

下列常數可用於設定 Level的值。 它們定義于 Microsoft Windows 驅動程式套件 (WDK) 標頭 dpfilter.h 和 Windows SDK 標頭 ntrtl.h:

#define   DPFLTR_ERROR_LEVEL     0
#define   DPFLTR_WARNING_LEVEL   1
#define   DPFLTR_TRACE_LEVEL     2
#define   DPFLTR_INFO_LEVEL      3
#define   DPFLTR_MASK   0x80000000

使用 Level 參數的其中一個簡單方式是一律使用介於 0 到 31 之間的值-- 使用位 0、1、2、3,並搭配 DPFLTR_XXXX所指定的意義_LEVEL,並使用其他位表示您選擇的任何值。

使用 Level 參數的另一個簡單方式是一律使用明確的位欄位。 如果您選擇此方法,建議您使用位欄位DPFLTR_MASK 或 值;這可確保您不會不小心使用小於 32 的值。

若要讓驅動程式與 Windows 使用訊息層級的方式相容,您應該只在發生嚴重錯誤時,設定重要性位欄位的最低位 (0x1) 。 如果您使用小於 32 的 Level 值,這會對應至DPFLTR_ERROR_LEVEL。 如果設定此位,每當有人將核心偵錯工具附加至驅動程式執行所在的電腦時,就會檢視您的訊息。

警告、追蹤和資訊層級應該用於適當的情況。 其他位可以自由用於您找到的任何用途。 這可讓您有各種不同的訊息類型,可選擇性地看到或隱藏。

DbgPrintKdPrint所傳送的所有訊息的行為就像是 Level等於 DPFLTR_INFO_LEVEL的DbgPrintExKdPrintEx訊息。 換句話說,這些訊息會設定其重要性位欄位的第三個位。

設定元件篩選遮罩

有兩種方式可以設定元件篩選遮罩:

  • 您可以在登錄機碼中存取元件篩選遮罩 ,HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Debug Print Filter。 使用登錄編輯器,建立或開啟此機碼。 在此機碼下,以大寫建立具有所需元件名稱的值。 將它設定為您想要作為元件篩選遮罩使用的 DWORD 值。

  • 如果核心偵錯工具處於作用中狀態,它可以藉由取值儲存在符號 Kd_XXXX_Mask的位址來存取元件篩選遮罩值,其中 XXXX 是所需的元件名稱。 您可以使用 dd (Display DWORD) 命令,在 WinDbg 或 KD 中顯示此遮罩的值,或使用 ded (Enter DWORD) 命令輸入新的元件篩選遮罩。 如果符號模棱兩可,您可能想要將此符號指定為 nt!Kd_XXXX_Mask

儲存在登錄中的篩選遮罩會在開機期間生效。 偵錯工具所建立的篩選遮罩會立即生效,並保存直到 Windows 重新開機為止。 偵錯工具可以覆寫登錄中設定的值,但如果系統重新開機,元件篩選遮罩就會回到登錄中指定的值。

另外還有一個名為 WIN2000的系統全遮罩。 這預設等於0x1,不過它可以透過登錄或偵錯工具變更,就像所有其他元件一樣。 執行篩選時,每個元件篩選遮罩都是使用 WIN2000 遮罩的第一個 ORed。 特別是,這表示從未指定遮罩的元件預設為0x1。

顯示訊息的準則

在核心模式程式碼中呼叫 DbgPrintEx 時,Windows 會比較 Level 所指定的訊息重要性位欄位與 ComponentId所指定元件的篩選遮罩。

注意

回想一下,當 Level參數介於 0 到 31 之間時,重要性位欄位等於 1 <<Level。 但是,當 Level 參數為 32 或更高版本時,重要性位欄位就等於 Level

Windows 會在重要性位欄位和元件篩選遮罩上執行 AND 作業。 如果結果為非零,訊息會傳送至偵錯工具。

偵錯篩選範例

假設在上一次開機之前,您已在 [偵錯 列印篩選 ] 機碼中建立下列值:

  • IHVVIDEO,其值等於 DWORD 0x2

  • IHVBUS,等於 DWORD 0x7FF

現在,您會在核心偵錯工具中發出下列命令:

kd> ed Kd_IHVVIDEO_Mask 0x8 
kd> ed Kd_IHVAUDIO_Mask 0x7 

此時 ,IHVVIDEO 元件具有0x8的篩選遮罩、 IHVAUDIO 元件具有0x7的篩選遮罩,而 IHVBUS 元件具有0x7FF的篩選遮罩。

不過,由於這些遮罩會自動使用全系統遮罩 WIN2000 ORed, (通常等於0x1) , 因此 IHVVIDEO 遮罩實際上等於0x9。 事實上, IHVSTREAMINGDEFAULT) 的篩選遮罩完全未設定 (的元件會有0x1的篩選遮罩。

現在假設下列函式調用發生在各種驅動程式中:

DbgPrintEx( DPFLTR_IHVVIDEO_ID,  DPFLTR_INFO_LEVEL,   "First message.\n");
DbgPrintEx( DPFLTR_IHVAUDIO_ID,  7,                   "Second message.\n");
DbgPrintEx( DPFLTR_IHVBUS_ID,    DPFLTR_MASK | 0x10,  "Third message.\n");
DbgPrint( "Fourth message.\n");

第一則訊息的 Level 參數等於 DPFLTR_INFO_LEVEL,也就是 3。 由於這小於 32,因此會被視為位移位,因此會產生0x8的重要性位欄位。 然後,這個值會以0x9的有效 IHVVIDEO 元件篩選遮罩進行 ANDed,以提供非零的結果。 因此,第一則訊息會傳送至偵錯工具。

第二則訊息的 Level 參數等於 7。 同樣地,這會被視為位移位,導致0x80的重要性位欄位。 接著,這是使用 0x7 的 IHVAUDIO 元件篩選遮罩進行 ANDed,結果為零。 因此,不會傳輸第二則訊息。

第三則訊息的 Level 參數等於 DPFLTR_MASK |0x10。 這大於 31,因此重要性位欄位會設定為等於 Level 的值,也就是0x80000010。 接著,這是使用 0x7FF 的 IHVBUS 元件篩選遮罩進行 ANDed,並提供非零的結果。 因此,第三則訊息會傳送至偵錯工具。

第四則訊息會傳遞至 DbgPrint ,而不是 DbgPrintEx。 在 Windows Server 2003 和舊版 Windows 中,傳遞至此常式的訊息一律會傳輸。 在 Windows Vista 和更新版本的 Windows 中,傳遞至此常式的訊息一律會獲得預設篩選。 重要性位欄位等於 1 << DPFLTR_INFO_LEVEL,也就是0x00000008。 這個常式的元件是 DEFAULT。 因為您尚未設定 DEFAULT 元件篩選遮罩,所以其值為 0x1。 當這是具有重要性位欄位的 ANDed 時,結果為零。 因此不會傳輸第四則訊息。

DbgPrint 緩衝區和偵錯工具

DbgPrint、DbgPrintExvDbgPrintEx、vDbgPrintExWithPrefixKdPrint 或 KdPrintEx常式將訊息傳送至偵錯工具時,格式化的字串會傳送至DbgPrint緩衝區。 除非您使用 GFlags 的 Buffer DbgPrint Output 選項停用此顯示,否則此緩衝區的內容會立即顯示在 [偵錯工具命令] 視窗中。

在本機核心偵錯期間,以及此顯示已停用的任何其他時間,只能使用 !dbgprint 擴充功能命令來檢視 DbgPrint 緩衝區的內容。

任何對DbgPrint、DbgPrintExvDbgPrintExvDbgPrintExWithPrefixKdPrint 或 KdPrintEx的單一呼叫只會傳輸 512 個位元組的資訊。 任何超過 512 個位元組的輸出都將遺失。 DbgPrint 緩衝區本身可以在 Windows 的免費組建上保存最多 4 KB 的資料,以及檢查的 Windows 組建上最多 32 KB 的資料。 在 Windows Server 2003 和更新版本的 Windows 上,您可以使用 KDbgCtrl 工具來改變 DbgPrint 緩衝區的大小。 此工具是 Windows 偵錯工具的一部分。

注意

在舊版 Windows 上,Windows 10 1803 版之前,已檢查的組建可供使用。 使用驅動程式驗證器和 GFlags 之類的工具,在更新版本的 Windows 中檢查驅動程式程式碼。

如果訊息因為 ComponentIdLevel 值而篩選掉,則不會跨偵錯連線傳輸訊息。 因此,在偵錯工具中無法顯示此訊息。