簡介
printk()是很多嵌入式開發者喜歡用的調試手段之一,但是,使用printk()每次都要重新編譯內核,很不方便。使用動態輸出在不需要重新編譯內核的情況下,方便的打印出內核的debug信息。
要開啟動態輸出,內核需要添加CONFIG_DYNAMIC_DEBUG。開啟宏之后,pr_debug(),dev_dbg() ,print_hex_dump_debug(),print_hex_dump_bytes()`所有信息都可以被動態打印出來。
動態輸出支持的特性
動態輸出在debugfs文件系統中對應的是control文件節點。control文件節點記錄了系統中所有使用動態輸出技術的文件名路徑,輸出語句所在的行號、模塊名和將要輸出的語句等。
你可以通過以下命令查看目前所有調試狀態的行為配置:
cat/sys/kernel/debug/dynamic_debug/control
你也可以應用標準的Unix文本過濾命令來過濾這些數據, 例如:
grep-irdma/sys/kernel/debug/dynamic_debug/control|wc-l
在第三列顯示了調試狀態位的激活標志。如果無額外行為被激話, 為 "=_"。因此你可以通過下面的命令查看任何不是默認標志的狀態位:
awk'$3!="=_"'/dynamic_debug/control
命令行使用方法
在語法層面上,一個命令由一系列的規格匹配組成,最后由一個標記來改變這規格。
command::=match-spec*flags-spec
match-spec常用來選擇一個已知的dprintk()調用點的子集來套用flags-spec。把他們當做彼此之間的每對做隱式查詢。注意,一個空的match_specs列表是有可能的,但不是非常有用,因為它不會匹配任何調用點的調試子句。
一個匹配規范由一個關鍵字組成,關鍵字控制被比較的調用點的屬性和要比較的值。可能關鍵字是:
match-spec::='func'string| 'file'string| 'module'string| 'format'string| 'line'line-range
line-range::=lineno| '-'lineno| lineno'-'| lineno'-'lineno
注意:line-range不能包含空格,例如,“1-30”是有效的范圍,但“1 - 30”就是無效的
每個關鍵字的含義如下:
func:給定的字符串會和每個調用點的函數名比較。例如:func svc_tcp_accept
file:給定的字符串會和每個調用點的源文件的全路徑名或者相對名比較。例如:file svcsock.c, file /usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svcsock.c
module:給定的字符串會和每個調用點的模塊名進行比較。模塊名是和在ls mod 里看到的字符串一樣。例如,module sunrpc
format:給定的字符串會在動態調試格式字符串里查找。注意這字符串不需要匹配這個格式。空格和其他特殊字符能夠用八進制字符語法來轉義,例如空字符是?40。作為選擇,這個字符串可以附上雙引號(")或者是單引號(‘)。例如:
formatsvcrdma://NFS/RDMA服務器的dprintks formatreadahead//一些在預加載緩存里的dprintks formatnfsd:?40SETATTR//一個使用空格來匹配格式的方式 format"nfsd:SETATTR"http://一個整齊的方法來用空格匹配格式 format'nfsd:SETATTR'//同樣是一個用空格來匹配格式的方法和
line:給定的行號或者是行號范圍會和每個dprintk()調用點的行號進行比較。例如:
line1603//準確定位到1603行 line1600-1605//1600行到1605行之間的6行 line-1605//從第一行到1605行之間的1605行 line1600-//從1600行到結尾的全部行
標記規范包含了一個由一個或多個標記字符跟隨的變化操作。這變化操作如下所示:
-//移除給定的標記 +//加入給定的標記 =//設置標記到給定的標記上 f//包含已打印消息的函數名 l//包含已在打印消息的行號 m//包含已打印消息的模塊名 p//產生一個printk()消息到顯示系統啟動日志 t//包含了不在中斷上下文中產生的消息里的線程ID
傳遞啟動參數給內核
在調試系統啟動是時,像USB核心初始化等,這些代碼在系統進入shell前已經初始化完畢,因此無法及時打開動態輸出語句。這時可以在內核啟動時傳遞參數給內核,在系統初始化時就打開它們。
例如,在內核命令行中添加 usbnet.dyndbg=+plft ,就可以在啟動時打開 usbnet的動態輸出。
在內核啟動后,通過 dmesg | grep "usbnet" 即可看到輸出的調試信息。
舉例
打開文件svcsock.c 1603行動態輸出語句
echo-n'filesvcsock.cline1603+p'>/sys/kernel/debug/dynamic_debug/control
打開文件svcsock.c所有動態輸出語句
echo-n'filesvcsock.c+p'>/sys/kernel/debug/dynamic_debug/control
打開NFS服務模塊所有動態輸出語句
echo-n'modulenfsd+p'>/sys/kernel/debug/dynamic_debug/control
打開函數svc_process()的所有動態輸出語句
echo-n'funcsvc_process+p'>/sys/kernel/debug/dynamic_debug/control
關閉函數svc_process()的所有動態輸出語句
echo-n'funcsvc_process-p'>/sys/kernel/debug/dynamic_debug/control
打開NFS調用的所有以READ開始的信息.
echo-n'format"nfsd:READ"+p'>/sys/kernel/debug/dynamic_debug/control
查看輸出的信息可以使用 dmesg | grep XXX 。也可以使用 tail -f /var/log/dmesg來實時監控dmesg的日志輸出。
審核編輯:湯梓紅
-
嵌入式
+關注
關注
5092文章
19177瀏覽量
307674 -
內核
+關注
關注
3文章
1382瀏覽量
40422 -
字符串
+關注
關注
1文章
585瀏覽量
20603 -
DEBUG
+關注
關注
3文章
94瀏覽量
19976
原文標題:使用動態輸出打印內核的DEBUG信息
文章出處:【微信號:嵌入式與Linux那些事,微信公眾號:嵌入式與Linux那些事】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論