驅動中列印訊息以及過濾機制

2021-09-24 14:31:35 字數 3295 閱讀 8757

在驅動開發中列印訊息主要使用dbgprint/kdprint函式,還有公升級版的dbgprintex/kdprintex。

dbg開頭的才是正統的api,而kd開頭的只是乙個巨集,最終呼叫的還是dbg***方法,kd版函式存在的意義是列印訊息在release版本中會被編譯器優化掉,不會產生**。

#if dbg 

#define kdprint(_x_) dbgprint _x_

#define kdprintex(_x_) dbgprintex _x_

#define vkdprintex(_x_) vdbgprintex _x_

#define vkdprintexwithprefix(_x_) vdbgprintexwithprefix _x_

#define kdbreakpoint() dbgbreakpoint()

#define kdbreakpointwithstatus(s) dbgbreakpointwithstatus(s)

#else

#define kdprint(_x_)

#define kdprintex(_x_)

#define vkdprintex(_x_)

#define vkdprintexwithprefix(_x_)

#define kdbreakpoint()

#define kdbreakpointwithstatus(s)

#endif

dbg巨集是用來判斷debug版本的,和windows sdk中_debug巨集是一樣的效果。

另外,kd版函式呼叫時需要兩對括號,像這樣。

kdprint(("kdprint\n"));
驅動訊息會用兩個引數表示其類別:元件(component)和等級(level)。在dpfilter.**件中有定義

//

// component name filter id enumeration and levels.

//#define dpfltr_error_level 0

#define dpfltr_warning_level 1

#define dpfltr_trace_level 2

#define dpfltr_info_level 3

#define dpfltr_mask 0x80000000

typedef enum _dpfltr_type dpfltr_type;

大部分都是系統使用的,留給開發者使用的一般只有以下幾個

dpfltr_ihvvideo_id

dpfltr_ihvaudio_id

dpfltr_ihvnetwork_id

dpfltr_ihvstreaming_id

dpfltr_ihvbus_id

dpfltr_ihvdriver_id

nt核心驅動一般用dpfltr_ihvdriver_id這個。level也預設了幾個

#define dpfltr_error_level 0

#define dpfltr_warning_level 1

#define dpfltr_trace_level 2

#define dpfltr_info_level 3

對於系統而言,它有乙個公式,如果把你提供的level帶入計算後結果是乙個非零值,就會將訊息傳送到偵錯程式,否則訊息會被過濾掉。

公式用一段c**表示可以寫成

unsigned calc(const unsigned filtermask, const unsigned level)

else

return filtermask & result;

}

如果level值介於0~31時就表示位移的位數,否則自身就是level值。得到的結果再與filtermask進行and操作,結果如果是非零的話就會被傳送給偵錯程式。我猜測這樣的設計是因為可以將level數量限制在32個以內,另乙個原因是就算你填了0也是可以的。

另乙個filtermask是哪來的呢?它是由系統提供的,這個掩碼預設是dpfltr_error_level,我們可以通過登錄檔來指定它

windows registry editor version 5.00

[hkey_local_machine\system\currentcontrolset\control\session manager\debug print filter]

"ihvdriver"=dword:00000008

當我們設定了掩碼後需要重啟計算機才可以生效。

上面這個登錄檔檔案是什麼意思呢?ihvdriver表示指定dpfltr_ihvdriver_id類別的掩碼,值8的二進位制是1000,根據計算公式,它是dpfltr_info_level移位後的結果。

那麼這麼設定後,dpfltr_ihvdriver_id類別的dpfltr_info_level級別訊息將會被傳送到偵錯程式。

在windows xp、windows server 2003系統上dbgprint函式不受訊息過濾機制的影響,將會暢通無阻的將訊息傳送到偵錯程式。

但是從vista系統開始,dbgprint函式被定義為dpfltr_info_level級別,而系統在預設情況下只會接受error_level的訊息,其他等級的訊息會被過濾掉,所以這也就造成了網上有很多類似"看不到dbgprint列印的訊息"這樣的提問。

如果繼續用dbgprint方法的話,則在vista以後的系統上你只能修改使用者系統的過濾掩碼(dpfltr_info_level)後才能看到訊息。

由於dbgprint在新的系統上被限制,所以建議使用可以指定component和level的dbgprintex函式。

kdprintex((dpfltr_ihvdriver_id, dpfltr_error_level, "dpfltr_error_level\n"));

kdprintex((dpfltr_ihvdriver_id, dpfltr_warning_level, "dpfltr_warning_level\n"));

kdprintex((dpfltr_ihvdriver_id, dpfltr_trace_level, "dpfltr_trace_level\n"));

kdprintex((dpfltr_ihvdriver_id, dpfltr_info_level, "dpfltr_info_level\n"));

根據過濾機制來看,我猜微軟是期望開發者只輸出嚴重的錯誤訊息,其他除錯跟蹤性的訊息應只在開發階段使用。

Windows訊息驅動

windows是乙個訊息驅動系統。它通過把訊息投入應用程式訊息佇列中或者把訊息傳送給合適的視窗訊息處理程式,將發生的各種事件通知給應用程式。要在視窗的顯示區域繪圖,可以使用windows的圖形裝置介面 gdi 函式。如 textout hdc,x,y,pstext,ilength 重繪 包括新的繪製...

訊息驅動bean

訊息驅動bean是處理通過jms傳遞的訊息的非同步訊息消費者。雖然mdb負責處理訊息,但是由執行mdb的ejb容器負責處理服務 事務,安全,資源,併發,訊息確認等 使bean開發者把精力集中在處理訊息的業務邏輯上。mdb在本質上是無狀態的,也就是說ejb容器可以執行大量的mdb例項,併發地處理各個應...

SpringCloud 訊息驅動

spring cloud stream由乙個中介軟體中立的核組成。應用通過spring cloud stream插入的input 相當於 消費者consumer,它是從佇列中接收訊息的 和output 相當於生產者producer,它是從佇列中傳送消 息的。通道與外界交流。通道通過指定中介軟體的bi...