讀取和篩選偵錯訊息
DbgPrintEx、vDbgPrintEx、vDbgPrintExWithPrefix和KdPrintEx常式會在您指定的條件下,將訊息傳送至核心偵錯工具。 此程式可讓您篩選掉低優先順序的訊息。
注意
在 Microsoft Windows Server 2003 和舊版 Windows 中, DbgPrint 和 KdPrint 常式會無條件地將訊息傳送至核心偵錯工具。 在 Windows Vista 和更新版本的 Windows 中,這些常式會有條件地傳送訊息,例如 DbgPrintEx 和 KdPrintEx。 無論您使用的 Windows 版本為何,您應該使用DbgPrintEx、vDbgPrintEx、vDbgPrintExWithPrefix和KdPrintEx,因為這些常式可讓您控制訊息傳送的條件。
篩選偵錯訊息
針對您想要傳送至偵錯工具的每個訊息,請在驅動程式的程式碼中使用DbgPrintEx、vDbgPrintEx、vDbgPrintExWithPrefix或KdPrintEx。 將適當的元件名稱傳遞至 ComponentId 參數,並將值傳遞至 Level 參數,以反映此訊息的嚴重性或本質。 訊息本身會使用與 printf相同的語法,傳遞至Format和引數參數。
設定適當 元件篩選遮罩的值。 每個元件都有不同的遮罩。 遮罩值會指出該元件的訊息顯示哪一個。 您可以使用登錄編輯器或在記憶體中使用核心偵錯工具,在登錄中設定元件篩選遮罩。
將核心偵錯工具附加至電腦。 每當驅動程式將訊息傳遞至DbgPrintEx、vDbgPrintEx、vDbgPrintExWithPrefix或KdPrintEx時,傳遞至ComponentId和Level的值都會與對應的元件篩選遮罩值進行比較。 如果這些值符合特定準則,訊息會傳送至核心偵錯工具並顯示。 否則,不會傳送任何訊息。
注意
此頁面上 DbgPrintEx 的所有參考都同樣適用于 KdPrintEx、 vDbgPrintEx和 vDbgPrintExWithPrefix。
識別元件名稱
每個元件都有個別的篩選遮罩。 這可讓偵錯工具個別設定每個元件的篩選。
每個元件會以不同的方式參考,視內容而定。 在DbgPrintEx的ComponentId參數中,元件名稱前面會加上 「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 作為DbgPrintEx的ComponentId參數、在登錄中使用值名稱IHVVIDEO,並在偵錯工具中參考Kd_IHVVIDEO_Mask。
DbgPrint和KdPrint所傳送的所有訊息都會與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。 如果設定此位,每當有人將核心偵錯工具附加至驅動程式執行所在的電腦時,就會檢視您的訊息。
警告、追蹤和資訊層級應該用於適當的情況。 其他位可以自由用於您找到的任何用途。 這可讓您有各種不同的訊息類型,可選擇性地看到或隱藏。
DbgPrint和KdPrint所傳送的所有訊息的行為就像是 Level等於 DPFLTR_INFO_LEVEL的DbgPrintEx和KdPrintEx訊息。 換句話說,這些訊息會設定其重要性位欄位的第三個位。
設定元件篩選遮罩
有兩種方式可以設定元件篩選遮罩:
您可以在登錄機碼中存取元件篩選遮罩 ,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。 事實上, IHVSTREAMING 或 DEFAULT) 的篩選遮罩完全未設定 (的元件會有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、DbgPrintEx、vDbgPrintEx、vDbgPrintExWithPrefix、KdPrint 或 KdPrintEx常式將訊息傳送至偵錯工具時,格式化的字串會傳送至DbgPrint緩衝區。 除非您使用 GFlags 的 Buffer DbgPrint Output 選項停用此顯示,否則此緩衝區的內容會立即顯示在 [偵錯工具命令] 視窗中。
在本機核心偵錯期間,以及此顯示已停用的任何其他時間,只能使用 !dbgprint 擴充功能命令來檢視 DbgPrint 緩衝區的內容。
任何對DbgPrint、DbgPrintEx、vDbgPrintEx、vDbgPrintExWithPrefix、KdPrint 或 KdPrintEx的單一呼叫只會傳輸 512 個位元組的資訊。 任何超過 512 個位元組的輸出都將遺失。 DbgPrint 緩衝區本身可以在 Windows 的免費組建上保存最多 4 KB 的資料,以及檢查的 Windows 組建上最多 32 KB 的資料。 在 Windows Server 2003 和更新版本的 Windows 上,您可以使用 KDbgCtrl 工具來改變 DbgPrint 緩衝區的大小。 此工具是 Windows 偵錯工具的一部分。
注意
在舊版 Windows 上,Windows 10 1803 版之前,已檢查的組建可供使用。 使用驅動程式驗證器和 GFlags 之類的工具,在更新版本的 Windows 中檢查驅動程式程式碼。
如果訊息因為 ComponentId 和 Level 值而篩選掉,則不會跨偵錯連線傳輸訊息。 因此,在偵錯工具中無法顯示此訊息。