前言
动态输出是内核子系统最喜欢的输出手段之一。在系统运行时,可以由系统维护者动态打开和关闭指定的printk()输出,也可以有选择地打开某些模块的输出,而printk 打印是全局的,只能设置输出等级,而且使用 printk 每次都要重新编译内核,很不方便。而动态输出可以在不需要重新编译内核的情况下,方便的打印出内核的 debug 信息。内核代码里大量使用了pr_debug()/pr_devel()来控制日志输出,其实这些函数本质还是通过printk进行打印的,所以本篇来讲解动态输出的使用,上篇没看printk的使用需要看完再看本篇内容
准备工作
使能动态输出宏开关
要使用动态打印,必须在内核配置时打开 CONFIG_DYNAMIC_DEBUG 宏。
CONFIG_DEBUG_FS=y
CONFIG_DYNAMIC_DEBUG=y
挂载debugfs
CONFIG_DYNAMIC_DEBUG 是配置动态输出,它依赖于 CONFIG_DEBUG_FS,而 CONFIG_DEBUG_FS 是 debugfs 文件系统。debugfs默认会挂载到 /sys/kernel/debug,如果没有挂载,可以执行以下命令挂载:
$ mount -t debugfs none /sys/kernel/debug
dynamic debug 的使用
这里我讲pr_debug和pr_devel的使用方法
pr_debug
pr_debug的定义
pr_debug 的定义在文件 include/linux/printk.h
/* If you are writing a driver, please use dev_dbg instead */
#if defined(CONFIG_DYNAMIC_DEBUG)
#include <linux/dynamic_debug.h>
/* dynamic_pr_debug() uses pr_fmt() internally so we don't need it here */
#define pr_debug(fmt, ...) \
dynamic_pr_debug(fmt, ##__VA_ARGS__)
#elif defined(DEBUG)
#define pr_debug(fmt, ...) \
printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__)
#else
#define pr_debug(fmt, ...) \
no_printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__)
#endif
需要注意的是KERN_DEBUG,默认的 console 打印级别是 7(在 kernel/printk/printk.c 中定义了 #define DEFAULT_CONSOLE_LOGLEVEL 4)。只有那些级别 "小于4" 的调试信息才能打印出来,而 pr_devel() 对应的 KERN_DEBUG 的级别是 7,那就还需要提高 console 打印级别到8
如果是 runtime,procfs 起来了,可以直接通过上篇说的 printk() 的 sys 接口调整打印级别
$ cat /proc/sys/kernel/printk
4 4 1 7
$ echo