【内核】动态输出接口 pr_debug 使用方法
測試環境:
運行環境:ubuntu-20.04
內核版本:5.10.0
一、接口簡介
在系統運行過程中,維護者可以通過控制pr_debug的開關來動態的配置某個模塊中的調試信息是否輸出,相對于printk來說,它顯然是更加靈活。
二、使用方法
如內核printk.h文件中定義:
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
可以看到通過配置可以分別實現有三種功能:
1)只有當CONFIG_DYNAMIC_DEBUG等宏已定義時,動態輸出功能才會真正的啟用,其核心是靠dynamic_pr_debug來實現,大概是通過將描述信息插入到section("__dyndbg")段內來進一步實現;
2)在引用到pr_debug接口的某個文件或某個模塊中,通過自定義一個DEBUG來配置它的第二種實現,這時候大家可以發現它就等同于printk,很直觀;
3)如果前兩種配置都不成立,那么好了,pr_debug將不會有任何的輸出。
三、實例測試
測試源碼:
【 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.
");
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.
");
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.12" /* 打開信息輸出開關 */ / # echo "file pr_dbg.c +p" > /sys/kernel/debug/dynamic_debug/control
大家有沒有想過,如果動態動態輸出的宏與DEBUG宏都定義了,那么會產生什么效果呢?
對應源碼的話不難發現,走的還是動態輸出的流程,只不過默認就是輸出調試信息了。
四、原理分析
動態輸出原理分析,暫時留白。
總結
以上是生活随笔為你收集整理的【内核】动态输出接口 pr_debug 使用方法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [Pytorch]Pytorch的ten
- 下一篇: 如何设置修改WPS批注上的用户信息名称