首页 > 其他分享 >使用动态输出打印内核的DEBUG信息

使用动态输出打印内核的DEBUG信息

时间:2023-01-15 22:44:54浏览次数:39  
标签:control 输出 打印 dynamic debug 内核 DEBUG line

简介

printk()是很多嵌入式开发者喜欢用的调试手段之一,但是,使用printk()每次都要重新编译内核,很不方便。使用动态输出在不需要重新编译内核的情况下,方便的打印出内核的debug信息。

要开启动态输出,内核需要添加CONFIG_DYNAMIC_DEBUG。开启宏之后,pr_debug(),dev_dbg()print_hex_dump_debug()print_hex_dump_bytes()`所有信息都可以被动态打印出来。

动态输出支持的特性

动态输出在debugfs文件系统中对应的是control文件节点。control文件节点记录了系统中所有使用动态输出技术的文件名路径,输出语句所在的行号、模块名和将要输出的语句等。

你可以通过以下命令查看目前所有调试状态的行为配置:

cat /sys/kernel/debug/dynamic_debug/control

你也可以应用标准的Unix文本过滤命令来过滤这些数据, 例如:

grep -i rdma /sys/kernel/debug/dynamic_debug/control  | wc -l

在第三列显示了调试状态位的激活标志。如果无额外行为被激话, 为 "=_"。 因此你可以通过下面的命令查看任何不是默认标志的状态位:

awk '$3 != "=_"' <debugfs>/dynamic_debug/control

命令行使用方法

在语法层面上,一个命令由一系列的规格匹配组成,最后由一个标记来改变这规格。

command ::= match-spec* flags-spec

match-spec常用来选择一个已知的dprintk()调用点的子集来套用flags-spec。把他们当做彼此之间的每对做隐式查询。注意,一个空的match_specs列表是有可能的,但不是非常有用,因为它不会匹配任何调用点的调试子句。

一个匹配规范由一个关键字组成,关键字控制被比较的调用点的属性和要比较的值。可能关键字是:

match-spec ::= 'func' string |
           'file' string |
           'module' string |
           'format' string |
           'line' line-range
line-range ::= lineno |
           '-'lineno |
           lineno'-' |
           lineno'-'lineno

注意:line-range不能包含空格,例如,“1-30”是有效的范围,但“1 - 30”就是无效的

每个关键字的含义如下:

  • func:给定的字符串会和每个调用点的函数名比较。例如: func svc_tcp_accept

  • file: 给定的字符串会和每个调用点的源文件的全路径名或者相对名比较。例如: file svcsock.cfile /usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svcsock.c

  • module: 给定的字符串会和每个调用点的模块名进行比较。模块名是和在ls mod 里看到的字符串一样。例如,module sunrpc

  • format:给定的字符串会在动态调试格式字符串里查找。注意这字符串不需要匹配这个格式。空格和其他特殊字符能够用八进制字符语法来转义,例如空字符是\040。作为选择,这个字符串可以附上双引号(")或者是单引号(‘)。例如:

  format svcrdma:     // NFS/RDMA 服务器的dprintks
  format readahead     // 一些在预加载缓存里的dprintks
  format nfsd:\040SETATTR // 一个使用空格来匹配格式的方式
  format "nfsd: SETATTR" // 一个整齐的方法来用空格匹配格式
  format 'nfsd: SETATTR' // 同样是一个用空格来匹配格式的方法和
  • line: 给定的行号或者是行号范围会和每个dprintk()调用点的行号进行比较。例如:
  line 1603     // 准确定位到1603行 
  line 1600-1605 //1600行到1605行之间的6行
  line -1605     // 从第一行到1605行之间的1605行
  line 1600-     // 从1600行到结尾的全部行

标记规范包含了一个由一个或多个标记字符跟随的变化操作。这变化操作如下所示:

- //移除给定的标记

+ //加入给定的标记

= //设置标记到给定的标记上 

f //包含已打印消息的函数名

l //包含已在打印消息的行号

m //包含已打印消息的模块名

p //产生一个printk()消息到显示系统启动日志

t //包含了不在中断上下文中产生的消息里的线程ID

传递启动参数给内核

在调试系统启动是时,像USB核心初始化等,这些代码在系统进入shell前已经初始化完毕,因此无法及时打开动态输出语句。这时可以在内核启动时传递参数给内核,在系统初始化时就打开它们。

例如,在内核命令行中添加 usbnet.dyndbg=+plft ,就可以在启动时打开 usbnet的动态输出。

在内核启动后,通过 dmesg | grep "usbnet" 即可看到输出的调试信息。

举例

打开文件svcsock.c 1603行动态输出语句

echo -n 'file svcsock.c line 1603 +p' > /sys/kernel/debug/dynamic_debug/control

打开文件svcsock.c所有动态输出语句

echo -n 'file svcsock.c +p' > /sys/kernel/debug/dynamic_debug/control

打开NFS服务模块所有动态输出语句

echo -n 'module nfsd +p' > /sys/kernel/debug/dynamic_debug/control

打开函数svc_process()的所有动态输出语句

echo -n 'func svc_process +p' > /sys/kernel/debug/dynamic_debug/control

关闭函数svc_process()的所有动态输出语句

echo -n 'func svc_process -p' > /sys/kernel/debug/dynamic_debug/control

打开NFS调用的所有以READ开始的信息.

echo -n 'format "nfsd: READ" +p' > /sys/kernel/debug/dynamic_debug/control

查看输出的信息可以使用 dmesg | grep XXX 。也可以使用 tail -f /var/log/dmesg来实时监控dmesg的日志输出。

本文参考

dynamic-debug-howto.txt

《奔跑吧Linux内核》

标签:control,输出,打印,dynamic,debug,内核,DEBUG,line
From: https://www.cnblogs.com/dongxb/p/17054397.html

相关文章

  • Execution failed for task ':app:checkDebugDuplicateClasses'解决办法
    Afailureoccurredwhileexecutingcom.android.build.gradle.internal.tasks.CheckDuplicatesRunnable >Duplicateclassandroid.support.v4.app.INotificationSi......
  • 内核转储的设置
    简介当程序运行的过程中异常终止或崩溃,操作系统会将程序当时的内存状态记录下来,保存在一个文件中,这种行为就叫做CoreDump(中文有的翻译成“核心转储”)。我们可以认为c......
  • uboot 传递参数给 kernel 内核
    uboot通过环境变量 bootargs传递参数给kernel内核,bootargs存储在设备树的chosen节点中,则kernel内核是通过读取设备树的chosen节点中的bootargs属性获取uboot......
  • 和菜鸟一起学linux内核源码之基础准备篇
        注:以下大部分内容摘自linux内核编程入门篇和linux内核完全注释       在工作的这段时间,发现我的visio画图熟悉了点点,总喜欢把什么源码啊,结构啊之类的就......
  • Linux内核机制—内核热补丁
    一、内核热补丁简介1.热补丁内核实现路径:kernel/livepatch/2.热补丁内核使用demo路径lib/livepatch/,可参考livepatch-sample.c实验也最简单。/*单独测试,使用新函......
  • 和菜鸟一起学linux内核之初始化init篇
    注:以下大部分内容摘自linux内核编程入门篇和linux内核完全注释      初始化init下只有一个main函数。      首先利用setup.s程序取得的程序参数设置系统的根......
  • 定义一个长度为3的数组并打印改数组
    packagecom.fqs.demo;importjava.util.Arrays;publicclassChongZ{publicstaticvoidmain(String[]args){int[]array=newint[3];//......
  • 微信h5之debug
    正常来说在微信任意一个聊天窗口输入:debugx5.qq.com,点击该链接就可以,但是我的安卓手机就报错了,说我使用的不是x5内核,解决办法:1.在微信窗口输入:debugtbs.qq.com,点开;2.根据......
  • 遍历打印数组在一行 实例
    一行打印数组packagecom.fqs.demo;publicclassChongZ{//数组遍历遍历显示整个数组显示在一行//publicstaticvoidmain(String[]args){......
  • 打印菱形
    #include<stdio.h>intmain(){intline=0;inti=0;scanf("%d",&line);//输入菱形上部分的行数,包括最长的一行//打印上部分for(i=0;i<line;i++){intj=0;......