服务器之家

服务器之家 > 正文

Linux内核中dev_info、dev_dbg、dev_err及动态调试

时间:2021-04-25 22:31     来源/作者:一口Linux

Linux内核中dev_info、dev_dbg、dev_err及动态调试

目前在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
  1. mkdir /mnt/dbg 
  2. mount -t debugfs none /mnt/dbg 
  • 使用下面方式控制你想输出dev_dbg()信息
  • 1.控制某个文件所有dev_dbg(),echo -n "file xxx.c +p" > /mnt/dbg/dynamic_debug/control
  • 2.控制某个函数所有dev_dbg(),echo -n "func xxx +p" > /mnt/dbg/dynamic_debug/control
  • 运行程序,使用dmesg则可以看到相应dev_dbg()的输出信息
  • 当调试结束,不再想输出dev_dbg()信息了,使用下面命令关闭即可
  • 1.echo -n "file xxx.c -p" > /mnt/dbg/dynamic_debug/control
  • 2.echo -n "func xxx -p" > /mnt/dbg/dynamic_debug/control

例子

  1. echo -n "file ca_dsc_core.c +p" > /mnt/dbg/dynamic_debug/control 则打印ca_dsc_core.c所有的dev_dbg()信息 
  2. 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解析出来:

  1. # cat /mnt/dbg/dynamic_debug/control 
  2. ... ... 
  3. ... ... 
  4. drivers/alidrivers/modules/alidsc/ca_dsc_core.c:800 [alidsc]ca_dsc_probe_dt =_ "get dev-index error12" 
  5. drivers/alidrivers/modules/alidsc/ca_dsc_core.c:789 [alidsc]ca_dsc_probe_dt =_ "get clk error12" 
  6. drivers/alidrivers/modules/alidsc/ca_dsc_core.c:292 [alidsc]ca_dsc_read =p "read: session#%d read returned %d bytes12" 
  7. drivers/alidrivers/modules/alidsc/ca_dsc_core.c:234 [alidsc]ca_dsc_read =p "read: session#%d read request: %zd bytes12" 
  8. drivers/alidrivers/modules/alidsc/ca_dsc_core.c:435 [alidsc]ca_dsc_vm_fault =_ "dsc_vm_fault: buffer#%d release %d bytes for session#%d12" 
  9. drivers/alidrivers/modules/alidsc/ca_dsc_core.c:112 [alidsc]ca_dsc_open =_ "dsc_se: failed register se12" 
  10. drivers/alidrivers/modules/alidsc/ca_dsc_core.c:755 [alidsc]ca_dsc_splice_write =_ "splice_write: session#%d dsc_from_pipe %d bytes12" 
  11. drivers/alidrivers/modules/alidsc/ca_dsc_core.c:729 [alidsc]ca_dsc_splice_write =_ "splice_write: session#%d count %zd bytes12" 
  12. drivers/alidrivers/modules/alidsc/ca_dsc_core.c:619 [alidsc]ca_dsc_splice_read =_ "splice_read: session#%d ret %zd bytes12" 
  13. drivers/alidrivers/modules/alidsc/ca_dsc_core.c:532 [alidsc]ca_dsc_splice_read =_ "splice_read: session#%d request %zd bytes12" 
  14. drivers/alidrivers/modules/alidsc/ca_dsc_core.c:871 [alidsc]ca_dsc_probe =_ "Get DSC handler error!12" 
  15. drivers/alidrivers/modules/alidsc/ca_dsc_core.c:820 [alidsc]ca_dsc_probe =_ "Failed to parse DT12" 
  16. drivers/alidrivers/modules/alidsc/ca_dsc_core.c:923 [alidsc]ca_dsc_remove =_ "get clk error12" 
  17. drivers/alidrivers/modules/alidsc/ca_dsc_core.c:396 [alidsc]ca_dsc_write =_ "write: session#%d ret %zd12" 
  18. drivers/alidrivers/modules/alidsc/ca_dsc_core.c:325 [alidsc]ca_dsc_write =_ "write: session#%d count %zd12" 
  19. ... ... 
  20. ... ... 
  21. net/ipv4/ping.c:965 [ping]ping_rcv =_ "no socket, dropping12" 
  22. net/ipv4/ping.c:960 [ping]ping_rcv =_ "rcv on socket %p12" 
  23. net/ipv4/ping.c:953 [ping]ping_rcv =_ "ping_rcv(skb=%p,id=%04x,seq=%04x)12" 
  24. net/ipv4/ping.c:932 [ping]ping_queue_rcv_skb =_ "ping_queue_rcv_skb -> failed12" 
  25. net/ipv4/ping.c:929 [ping]ping_queue_rcv_skb =_ "ping_queue_rcv_skb(sk=%p,sk->num=%d,skb=%p)12" 
  26. net/ipv4/ping.c:921 [ping]ping_recvmsg =_ "ping_recvmsg -> %d12" 
  27. net/ipv4/ping.c:840 [ping]ping_recvmsg =_ "ping_recvmsg(sk=%p,sk->num=%u)12" 
  28. net/ipv4/ping.c:693 [ping]ping_v4_sendmsg =_ "ping_v4_sendmsg(sk=%p,sk->num=%u)12" 
  29. net/ipv4/ping.c:197 [ping]ping_lookup =_ "found: %p: num=%d, daddr=%pI4, dif=%d12" 
  30. net/ipv4/ping.c:189 [ping]ping_lookup =_ "iterate12" 
  31. net/ipv4/ping.c:176 [ping]ping_lookup =_ "try to find: num = %d, daddr = %pI4, dif = %d12" 
  32. net/ipv4/ping.c:505 [ping]ping_err =_ "err on socket %p12" 
  33. net/ipv4/ping.c:502 [ping]ping_err =_ "no socket, dropping12" 
  34. net/ipv4/ping.c:498 [ping]ping_err =_ "ping_err(proto=0x%x,type=%d,code=%d,id=%04x,seq=%04x)12" 
  35. net/ipv4/ping.c:304 [ping]ping_check_bind_addr =_ "ping_check_bind_addr(sk=%p,addr=%pI4,port=%d)12" 
  36. net/ipv4/ping.c:445 [ping]ping_bind =_ "ping_v4_bind -> %d12" 
  37. net/ipv4/ping.c:423 [ping]ping_bind =_ "after bind(): num = %d, dif = %d12" 
  38. net/ipv4/ping.c:286 [ping]ping_close =_ "isk->refcnt = %d12" 
  39. net/ipv4/ping.c:285 [ping]ping_close =_ "ping_close(sk=%p,sk->num=%u)12" 
  40. net/ipv4/ping.c:153 [ping]ping_unhash =_ "ping_unhash(isk=%p,isk->num=%u)12" 
  41. net/ipv4/ping.c:146 [ping]ping_hash =_ "ping_hash(sk->port=%u)12" 
  42. net/ipv4/ping.c:67 [ping]ping_hashfn =_ "hash(%d) = %d12" 
  43. net/ipv4/ping.c:130 [ping]ping_get_port =_ "was not hashed12" 
  44. net/ipv4/ping.c:127 [ping]ping_get_port =_ "found port/ident = %d12" 

以其中一条为例子:

  1. drivers/alidrivers/modules/alidsc/ca_dsc_core.c:800 [alidsc]ca_dsc_probe_dt =_ "get dev-index error12" 则不会打印 
  2. drivers/alidrivers/modules/alidsc/ca_dsc_core.c:800 [alidsc]ca_dsc_probe_dt =p "get dev-index error12" 则会打印 

所以在应用层,用户就可以通过使用echo来控制dynamic_debug/control文件,进而控制是否打印某个dev_dbg()信息!

  • dev_dbg()对于分析某些内核子系统或者驱动流程也十分有意义,例如,使能net/ipv4/ping.c的调试开关,则可以观测ping的运行原理。

代码分析

 

从代码角度,也很容易看出dev_dbg()的设计:

  1. include/linux/device.h include/linux/dynamic_debug.h lib/dynamic_debug.c 
  1. //使能CONFIG_DYNAMIC_DEBUG后则根据control信息动态打印 
  2. #if defined(CONFIG_DYNAMIC_DEBUG) 
  3.  #define dev_dbg(dev, format, ...)        
  4.  do {            
  5.   dynamic_dev_dbg(dev, format, ##__VA_ARGS__);  
  6.  } while (0) 
  7. //使能DEBUG,则打印整个kernel的dev_dbg信息 
  8. #elif defined(DEBUG) 
  9.  #define dev_dbg(dev, format, arg...)   
  10.   dev_printk(KERN_DEBUG, dev, format, ##arg) 
  11. //都不使能,dev_dbg不打印任何东西 
  12. #else 
  13.  #define dev_dbg(dev, format, arg...)     
  14.  ({         
  15.   if (0)        
  16.    dev_printk(KERN_DEBUG, dev, format, ##arg);  
  17.   0;        
  18.  }) 
  19. #endif 

下面的dynamic_dev_dbg()实现显然可以看出,打印是根据descriptor的标志位_DPRINTK_FLAGS_PRINT进行打印的,而标志位是可以通过dbgfs进行控制的。

  1. #define dynamic_dev_dbg(dev, fmt, ...)     
  2. do {         
  3.  DEFINE_DYNAMIC_DEBUG_METADATA(descriptor, fmt);   
  4.  if (unlikely(descriptor.flags & _DPRINTK_FLAGS_PRINT))  
  5.   __dynamic_dev_dbg(&descriptor, dev, fmt,  
  6.       ##__VA_ARGS__);   
  7. } while (0) 

好处

 

开发版本,打开CONFIG_DYNAMIC_DEBUG和CONFIG_DEBUG_FS,配合dbgfs动态观测和调试内核代码;

正式版本,关闭CONFIG_DYNAMIC_DEBUG和CONFIG_DEBUG_FS,所有dbgfs以及dev_dbg信息都从编译阶段自动移除;

原文地址:https://mp.weixin.qq.com/s/0qy8XkSoL-_keGo97aK2Cg

标签:

相关文章

热门资讯

2022年最旺的微信头像大全 微信头像2022年最新版图片
2022年最旺的微信头像大全 微信头像2022年最新版图片 2022-01-10
蜘蛛侠3英雄无归3正片免费播放 蜘蛛侠3在线观看免费高清完整
蜘蛛侠3英雄无归3正片免费播放 蜘蛛侠3在线观看免费高清完整 2021-08-24
背刺什么意思 网络词语背刺是什么梗
背刺什么意思 网络词语背刺是什么梗 2020-05-22
yue是什么意思 网络流行语yue了是什么梗
yue是什么意思 网络流行语yue了是什么梗 2020-10-11
暖暖日本高清免费中文 暖暖在线观看免费完整版韩国
暖暖日本高清免费中文 暖暖在线观看免费完整版韩国 2021-05-08
返回顶部

1899
Weibo Article 1 Weibo Article 2 Weibo Article 3 Weibo Article 4 Weibo Article 5 Weibo Article 6 Weibo Article 7 Weibo Article 8 Weibo Article 9 Weibo Article 10 Weibo Article 11 Weibo Article 12 Weibo Article 13 Weibo Article 14 Weibo Article 15 Weibo Article 16 Weibo Article 17 Weibo Article 18 Weibo Article 19 Weibo Article 20 Weibo Article 21 Weibo Article 22 Weibo Article 23 Weibo Article 24 Weibo Article 25 Weibo Article 26 Weibo Article 27 Weibo Article 28 Weibo Article 29 Weibo Article 30 Weibo Article 31 Weibo Article 32 Weibo Article 33 Weibo Article 34 Weibo Article 35 Weibo Article 36 Weibo Article 37 Weibo Article 38 Weibo Article 39 Weibo Article 40