https://xuesong.blog.csdn.net/article/details/109522945?spm=1001.2014.3001.5502
使用动态输出是系统内核调试的重要手段之一。
内核使用大量的pr_debug()/dev_dbg()函数来输出信息,使用了动态输出的技术。在使用动态输出时,记住需要挂载debugfs文件系统。
debugfs文件系统对应control节点,记录所有使用动态输出技术的文件名路径、输出语句所在的行号、模块号和将要输出的语句等。
在系统运行时候,动态打印可以由系统维护者动态打开内核子系统的打印,可以有选择性地打开某些模块的打印,而printk是全局的,只能设置打印等级。要使用动态打印,必须在内核配置时打开CONFIG DYNAMIC DEBUG宏。
benshushu:dynamic_debug# less control
# filename:lineno [module]function flags format
init/main.c:770 [main]initcall_blacklist =p "blacklisting initcall %s\012"
init/main.c:803 [main]initcall_blacklisted =p "initcall %s blacklisted\012"
使用举例:
# 打开svcsock.c文件中所有动态输出语句
#echo 'file svcsock.c +p' > /sys/kernel/debug/dynamic_debug/control
# 打开usbcore模块的所有动态输出语句
#echo 'module usbcore +p' > /sys/kernel/debug/dynamic_debug/control
# 打开svc_process()函数中所有动态输出语句
#echo 'func svc_process() +p' > /sys/kernel/debug/dynamic_debug/control
#关闭svc_process()函数中所有动态输出语句
#echo 'func svc_process() -p' > /sys/kernel/debug/dynamic_debug/control
#打开文件路径包含usb的文件里所有动态输出语句
#echo -n '*usb* +p' > /sys/kernel/debug/dynamic_debug/control
#打开系统所有动态输出语句
#echo -n '+p' > /sys/kernel/debug/dynamic_debug/control
上面是动态打印语句的例子。除了能打印pr_debug()/dev_dbg()函数中定义的输出外,还能打印一些额外信息。例如函数名、行号、模块名字和线程ID等。
p:打开输出动态输出语句
f:输出函数名
l:输出行号
m:输出模块名
t:输出线程ID
对于一些在shell之前就启动模块,调试起来,使用动态输出的方法:
先找到topology
benshushu:dynamic_debug# cat control | grep topology
arch/arm64/kernel/topology.c:291 [topology]store_cpu_topology =_ "CPU%u: cluster %d core %d thread %d mpidr %#016llx\012"
然后再进行在启动参数上添加:topology.dyndgb=+plft字符串
还可以在子系统Makefile中打开ccflags来打开动态输出功能:
ccflags-y := -DDEBUG
ccflags-y += -DVERBOSE_DEBUG
dynamic动态打印可以通过宏定义巧妙转为printk正常打印:
//c文件开头添加如下代码:
#undef dev_dbg
#define dev_dbg dev_info
#undef pr_debug
#define pr_debug pr_info