目前在 kernel 驱动代码中,都不再建议直接使用printk
直接添加打印信息,而是使用dev_info
,dev_dbg
,dev_err
之类的函数代替,虽然这些dev_xxx
函数的本质还是使用printk
打印的,但是相比起printk
:
- 支持打印模块信息、dev 信息
- 支持动态调试 (dynamic debug) 方式
下面简述下这几个dev_xxx
函数的基本使用规则,以及动态调试使用方式。
- dev_info(): 启动过程、或者模块加载过程等 “通知类的” 信息等,一般只会通知一次,例如 probe 函数;
- dev_dbg(): 一般使用在普通错误,如-EINVAL、-ENOMEM 等 errno 发生处,用于调试;
- dev_err(): 一般使用在严重错误,尤其是用户无法得到 errno 的地方,或者程序员不容易猜测系统哪里出了问题的地方;
动态调试使用方法
- 打开内核动态调试开关,
make menuconfig
选中CONFIG_DYNAMIC_DEBUG
以及CONFIG_DEBUG_FS
- Linux 启动后,使用命令行挂载上 dbgfs
mkdir /mnt/dbg
mount -t debugfs none /mnt/dbg
- 使用下面方式控制你想输出 dev_dbg() 信息
- 控制某个文件所有 dev_dbg(),
echo -n "file xxx.c +p" > /mnt/dbg/dynamic_debug/control
- 控制某个函数所有 dev_dbg(),
echo -n "func xxx +p" > /mnt/dbg/dynamic_debug/control
- 控制某个文件所有 dev_dbg(),
- 运行程序,使用 dmesg 则可以看到相应 dev_dbg() 的输出信息
- 当调试结束,不再想输出 dev_dbg() 信息了,使用下面命令关闭即可
echo -n "file xxx.c -p" > /mnt/dbg/dynamic_debug/control
echo -n "func xxx -p" > /mnt/dbg/dynamic_debug/control
例子
echo -n "file ca_dsc_core.c +p" > /mnt/dbg/dynamic_debug/control
则打印ca_dsc_core.c
所有的 dev_dbg() 信息echo -n "func ca_dsc_read +p" > /mnt/dbg/dynamic_debug/control
则打印ca_dsc_read()
函数所有 dev_dbg() 信息
动态打印调试的基本原理
当编译选项CONFIG_DYNAMIC_DEBUG
打开的时候,在编译阶段,kernel 会把所有使用 dev_dbg() 的信息记录在一个 table 中,这些信息我们可以从/mnt/dbg/dynamic_debug/control
解析出来:
# cat /mnt/dbg/dynamic_debug/control
... ...
... ...
drivers/alidrivers/modules/alidsc/ca_dsc_core.c:800 [alidsc]ca_dsc_probe_dt =_ "get dev-index error