简介

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内核》

使用动态输出打印内核的DEBUG信息的更多相关文章

  1. log4j配置只打印指定jar或包的DEBUG信息

    有的时候查问题的时候需要打印第三方jar里面的debug信息,假如全部jar都打印的话日志文件会很大,这个时候可以配置log4j只打印指定jar的debug信息或者包,同时输出到了一个新的文件中. 比 ...

  2. cocos2d-x 输出debug信息

    cocos2d-x 输出debug信息   在Classes目录下添加文件AppDef.h #ifndef _APP_DEF_H_#define _APP_DEF_H_ #include <an ...

  3. go frame框架,关闭启动时打印的路由列表已经debug信息

    import ( "github.com/gogf/gf/frame/g" "github.com/gogf/gf/os/glog" ) func main() ...

  4. IOS调试—断点调试以及动态输出

    在开发App的过程中,需要反复的修改和优化我们的代码,特别是当程序出现bug,需要快速的找出错误的原因,进行修改,以保证程序的正确执行. 断点调试,是最常用最简单的一种调试方式,可以一步步跟踪程序执行 ...

  5. 【技巧】Java工程中的Debug信息分级输出接口

    也许本文的标题你们没咋看懂.但是,本文将带大家领略输出调试的威力. 灵感来源 说到灵感,其实是源于笔者在修复服务器的ssh故障时的一个发现. 这个学期初,同袍(容我来一波广告产品页面,同袍官网)原服务 ...

  6. 【技巧】Java工程中的Debug信息分级输出接口及部署模式

    也许本文的标题你们没咋看懂.但是,本文将带大家领略输出调试的威力. 灵感来源 说到灵感,其实是源于笔者在修复服务器的ssh故障时的一个发现. 这个学期初,同袍(容我来一波广告产品页面,同袍官网)原服务 ...

  7. uname---用于打印当前系统相关信息

    uname命令用于打印当前系统相关信息(内核版本号.硬件架构.主机名称和操作系统类型等). 语法 uname(选项) 选项 -a或--all:显示全部的信息: -m或--machine:显示电脑类型: ...

  8. linux 将debug信息重定向到LCD(屏幕)

    /*********************************************************************** * linux 将debug信息重定向到LCD(屏幕) ...

  9. FFmpeg开发实战(三):FFmpeg 打印音视频Meta信息

    在之前使用FFmpeg命令行的时候,我们经常看到FFmpeg命令行在输出音视频文件的会打印一下文件的Meta信息,类似如图: 那么我们如何通过代码的方式输出这些Meta信息呢? FFmpeg提供了一个 ...

  10. log4j 配置,tomcat 启动或有后台操作时,控制台会显示很多 DEBUG 信息

    log4j 配置,tomcat 启动或有后台操作时,控制台会显示很多 DEBUG 信息 日志信息可以以文件形式显示,也可以在控制台输出,在 log4j.properties 文件设置. 控制台有很多 ...

随机推荐

  1. SpringCloud整合分布式事务Seata 1.4.1 支持微服务全局异常拦截

    项目依赖 SpringBoot 2.5.5 SpringCloud 2020.0.4 Alibaba Spring Cloud 2021.1 Mybatis Plus 3.4.0 Seata 1.4. ...

  2. Tensorflow Lite从入门到精通

    TensorFlow Lite 是 TensorFlow 在移动和 IoT 等边缘设备端的解决方案,提供了 Java.Python 和 C++ API 库,可以运行在 Android.iOS 和 Ra ...

  3. windows下cmd补全键注册表修改

      1:使用win+r打开 运行 控制台 2:输入 regedit 打开注册表 3:进入HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Command Processor\ ...

  4. 二十九、Helm常用命令

    # 创建一个chart范例 helm create HELM-NAME # 检查chart语法 helm lint ./HELM-NAME # 使用默认chart部署到k8s helm install ...

  5. CSS基础知识筑基

    01.CSS 简介 CSS 指层叠样式表 (Cascading Style Sheets),对HTML网页内容进行统一外观样式设计和管理,给网页进行各种装饰,让她变得美观,是HTML的化妆师.(Cas ...

  6. Golang 和Python 几个小时前 几分钟 几天前的处理

    在用golang爬虫的时候 总会遇到 10天前 10分钟前 刚刚这种很影响我们爬取正常事件 所以我写了个方法 来格式化这种事件 golang 版本 package utils import ( &qu ...

  7. 重新整理 .net core 实践篇 ———— linux上性能排查 [外篇]

    前言 该文的前置篇为: https://www.cnblogs.com/aoximin/p/16839830.html 本文介绍性能排查. 正文 上一节是出现错误了,如何去排查具体问题. 这一节介绍一 ...

  8. C#字典出错“集合已经修改,可能无法执行枚举操作”

    出现这个现象的原因是由于线程安全考虑,如果你边对字典循环,又同时移除字典中的某个键值对, 那么将会出现这种错误,解决这种问题的方法是你没次remove某个键值对后需要break结束对字典的循环.

  9. 根据MediatR的Contract Messages自动生成Minimal WebApi接口

    大家好,我是失业在家,正在找工作的博主Jerry.今天给大家介绍一个能大大减少ASP.Net Minimal WebApi编码量的方法. 我们一般会把微服务的VO和DTO封装成消息类,并作为WebAp ...

  10. [.NET学习] EFCore学习之旅 -3 一些其他的迁移命令

    1.Update-DataBase  xxx 概述:将数据库回滚到某个版本. 1.首先创建一个表 Dog 2.生成迁移 Add-Migration CreateDogTable 并更新到数据库 Upd ...