【內核】動態輸出接口 pr_debug 使用方法

測試環境:linux

運行環境:ubuntu-20.04git

內核版本:5.10.0github

 

1、接口簡介ubuntu

在系統運行過程當中,維護者能夠經過控制 pr_debug 的開關來動態的配置某個模塊中的調試信息是否輸出,相對於 printk 來講,它顯然是更加靈活。測試

 

2、使用方法ui

 如內核 printk.h 文件中定義:spa

 1 /* If you are writing a driver, please use dev_dbg instead */
 2 #if defined(CONFIG_DYNAMIC_DEBUG) || \
 3     (defined(CONFIG_DYNAMIC_DEBUG_CORE) && defined(DYNAMIC_DEBUG_MODULE))  4 #include <linux/dynamic_debug.h>
 5 
 6 /**  7  * pr_debug - Print a debug-level message conditionally  8  * @fmt: format string  9  * @...: arguments for the format string 10  * 11  * This macro expands to dynamic_pr_debug() if CONFIG_DYNAMIC_DEBUG is 12  * set. Otherwise, if DEBUG is defined, it's equivalent to a printk with 13  * KERN_DEBUG loglevel. If DEBUG is not defined it does nothing. 14  * 15  * It uses pr_fmt() to generate the format string (dynamic_pr_debug() uses 16  * pr_fmt() internally). 17  */
18 #define pr_debug(fmt, ...)            \
19  dynamic_pr_debug(fmt, ##__VA_ARGS__) 20 #elif defined(DEBUG)
21 #define pr_debug(fmt, ...) \
22  printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__) 23 #else
24 #define pr_debug(fmt, ...) \
25  no_printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__) 26 #endif

能夠看到經過配置能夠分別實現有三種功能: debug

1)只有當 CONFIG_DYNAMIC_DEBUG 等宏已定義時,動態輸出功能纔會真正的啓用,其核心是靠 dynamic_pr_debug 來實現,大概是經過將描述信息插入到 section("__dyndbg") 段內來進一步實現;調試

2)在引用到 pr_debug 接口的某個文件或某個模塊中,經過自定義一個 DEBUG 來配置它的第二種實現,這時候你們能夠發現它就等同於 printk,很直觀;code

3)若是前兩種配置都不成立,那麼好了, pr_debug 將不會有任何的輸出。 

 

3、實例測試

測試源碼:

【 pr_dbg.c 】

 1 #include <linux/kernel.h>
 2 #include <linux/module.h>
 3 #include <linux/init.h>
 4 #include <linux/timer.h>
 5 #include <linux/printk.h>
 6 
 7 static struct timer_list timer = {0};  8 
 9 void timer_handler(struct timer_list *t) 10 { 11     pr_debug("pr_dbg: This is pr_init func.\n"); 12     mod_timer(&timer, jiffies+msecs_to_jiffies(5000)); 13 } 14 
15 static int pr_test_init(void) 16 { 17     timer_setup(&timer, timer_handler, 0); 18     timer.expires = jiffies + 5 * HZ; 19     add_timer(&timer); 20 
21     return 0; 22 } 23 
24 static int pr_init(void) 25 { 26  pr_test_init(); 27     printk("pr_init exec finished.\n"); 28 
29     return 0; 30 } 31 
32 static void pr_exit(void) 33 { 34     del_timer(&timer); 35 } 36 
37 module_init(pr_init); 38 module_exit(pr_exit); 39 MODULE_LICENSE("GPL"); 40 MODULE_AUTHOR("Zackary.Liu");

【 Makefile 】 :

 1 kernel_path := /root/github/linux  2 
 3 all:  4         make -C ${kernel_path} M=`pwd` modules  5 #KCFLAGS=-DDEBUG  6 
 7 clean:  8         make -C ${kernel_path} M=`pwd` clean  9 
10 obj-m += pr_dbg.o

1)先測試第二種配置吧,比較簡單一些,如上面說過的只要定義一個 DEBUG 便可以實現,那麼咱們直接就在 Makefile 中加入好,

將編譯指令改成: make -C ${kernel_path} M=`pwd` modules KCFLAGS+=-DDEBUG 便可。

將模塊編譯好並安裝,能夠看到有 pr_dbg: This is pr_init func. 信息輸出。

2)配置爲動態輸出,首先須要打開內核相關配置,並編譯替換爲新內核:

藉助 debugfs 下的 control 接口,寫入相應的指令便可控制動態輸出的開關,開關默認是關閉的:

/* 先查找對應信息 */
/ # cat /sys/kernel/debug/dynamic_debug/control | grep pr_dbg /root/kernel_modules/01-dev_dbg/pr_dbg.c:11 [pr_dbg]timer_handler =_ "pr_dbg: This is pr_init func.\012"
/* 打開信息輸出開關 */
/ # echo "file pr_dbg.c +p" > /sys/kernel/debug/dynamic_debug/control

你們有沒有想過,若是動態動態輸出的宏與 DEBUG 宏都定義了,那麼會產生什麼效果呢?

對應源碼的話不難發現,走的仍是動態輸出的流程,只不過默認就是輸出調試信息了。

 

4、原理分析

動態輸出原理分析,暫時留白。

相關文章
相關標籤/搜索