Linux内核基础篇——动态输出调试

news2024/11/24 22:48:17

动态输出调试

文章目录

    • 配置内核编译选项
    • debugfs文件系统挂载
    • 动态输出使用
    • 实际案例


动态输出(dynamic print)是内核子系统开发者最喜欢的输出技术之一。

上篇说到printk调试,但printk是全局的,只能设置输出等级。而动态输出可以动态选择打开某个内核子系统的输出,可以有选择性地打开某些模块的输出。

配置内核编译选项

要使用动态输出,必须在配置内核时打开CONFIG_DYNAMIC_DEBUG宏。内核代码里使用大量pr_debug()/dev_dbg()函数来输出信息,这些就使用了动态输出。

需要打开的内核配置选项:

CONFIG_DEBUG_FS=y
CONFIG_DYNAMIC_DEBUG=y

img

CONFIG_DYNAMIC_DEBUG是配置动态输出,它依赖于CONFIG_DEBUG_FS,而CONFIG_DEBUG_FSdebugfs文件系统

打开内核配置后,我们还需要挂载debugfs文件系统

debugfs文件系统挂载


动态输出在debugfs文件系统中有一个control文件节点,这个文件节点记录了系统中所有使用动态输出技术的文件名路径、输出所在的行号、模块名字和要输出的语句

debugfs默认会挂载到/sys/kernel/debug,如果没有挂载,可以执行以下命令挂载:

# mount -t debugfs none /sys/kernel/debug/

挂载debugfs文件系统后,可以查看control节点内容:

# cat /sys/kernel/debug/dynamic_debug/control

动态输出使用


打开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

打开文件路径包含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

另外,还可以在各个子系统的Makefile中添加ccflags来打开动态输出语句

<../Makefile>

ccflags-y += -DDEBUG
ccflags-y += -DVERBOSE_DEBUG

实际案例


例如在一个led驱动中的open()、write()等函数开头添加一句pr_debug(“%s enter\n”, __ func__);

#include <linux/module.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/miscdevice.h>
#include <linux/kernel.h>
#include <linux/major.h>
#include <linux/mutex.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/stat.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/tty.h>
#include <linux/kmod.h>
#include <linux/gfp.h>

static int major = 0;
static char kernel_buf[1024];
static struct class *hello_class;

#define MIN(a, b) (a < b ? a : b)

static ssize_t hello_drv_read (struct file *file, char __user *buf, size_t size, loff_t *offset)
{
 int err;
 pr_debug("%s enter\n", __func__);

 err = copy_to_user(buf, kernel_buf, MIN(1024, size));
 return MIN(1024, size);
}

static ssize_t hello_drv_write (struct file *file, const char __user *buf, size_t size, loff_t *offset)
{
 int err;
 pr_debug("%s enter\n", __func__);
 err = copy_from_user(kernel_buf, buf, MIN(1024, size));
 return MIN(1024, size);
}

static int hello_drv_open (struct inode *node, struct file *file)
{
 pr_debug("%s enter\n", __func__);
 return 0;
}

static int hello_drv_close (struct inode *node, struct file *file)
{
 pr_debug("%s enter\n", __func__);
 return 0;
}

/* 2. 定义自己的file_operations结构体                                              */
static struct file_operations hello_drv = {
 .owner  = THIS_MODULE,
 .open    = hello_drv_open,
 .read    = hello_drv_read,
 .write   = hello_drv_write,
 .release = hello_drv_close,
};

static int __init hello_init(void)
{
 int err;
 
 pr_debug("%s enter\n", __func__);
 major = register_chrdev(0, "hello", &hello_drv);  /* /dev/hello */

 hello_class = class_create(THIS_MODULE, "hello_class");
 err = PTR_ERR(hello_class);
 if (IS_ERR(hello_class)) {
  unregister_chrdev(major, "hello");
  return -1;
 }
 
 device_create(hello_class, NULL, MKDEV(major, 0), NULL, "hello"); /* /dev/hello */
 
 return 0;
}

static void __exit hello_exit(void)
{
 pr_debug("%s enter\n", __func__);
 device_destroy(hello_class, MKDEV(major, 0));
 class_destroy(hello_class);
 unregister_chrdev(major, "hello");
}

module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL");

为了方面查看,先清除内核输出:

# dmesg -c

然后加载驱动,执行dmesg查看是否有打印:

# insmod hello_drv.ko
# dmesg

img

此时没有pr_debug()的打印。这时再使用动态输出打开hello_drv模块的动态输出:

# echo 'module hello_drv +p' > /sys/kernel/debug/dynamic_debug/control

然后执行该驱动的应用层程序,使其调用到驱动的open、write、close函数,从而执行pr_debug():

# ./hello_drv_test -w 10

再查看demsg内容:

img

可以看到,当打开了hello_drv模块的动态输出后,驱动中的pr_debug()语句就可以正常打印了。

再看看debugfs的control节点:

# cat /sys/kernel/debug/dynamic_debug/control

img

control节点记录了刚刚执行pr_debug()时的文件名、所在行号、模块名、函数名和输出语句(p表示动态输出的语句)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/100143.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Tensorflow Serving部署推荐模型

Tensorflow Serving部署推荐模型 1、找到当前模型中定义的variables&#xff0c;并在此定义一个saver用于保存模型参数 def saveVariables(self):variables_dict {}variables_dict[self.user_embedding.op.name] self.user_embeddingvariables_dict[self.item_embedding.op…

【LeetCode】1971. 寻找图中是否存在路径

题目描述 有一个具有 n 个顶点的 双向 图&#xff0c;其中每个顶点标记从 0 到 n - 1&#xff08;包含 0 和 n - 1&#xff09;。图中的边用一个二维整数数组 edges 表示&#xff0c;其中 edges[i] [ui, vi] 表示顶点 ui 和顶点 vi 之间的双向边。 每个顶点对由 最多一条 边连…

犀牛插件开发-基础核心-技术概览-总体架构-教程

文章目录1.概述2.基础核心2.1.C Rhino 核心2.2.openNURBS2.3.C SDK3.C Stack3.1.C Plugins3.2.RhinoScript4.NET Stack4.1.C API4.2.NET Framework4.3.RhinoCommon4.4.Eto4.5.net插件4.6.Grasshopper组件4.7.Python脚本5.相关主题1.概述 《Rhinoceros》由许多层组成——用多种…

细说OA系统的繁荣发展

改革开放以来&#xff0c;科技发展突飞猛进&#xff0c;我们生活的方方面面都受到了巨大影响。随着信息化时代的到来&#xff0c;企业的办公方式也发生了巨大的改变&#xff0c;OA系统随之走进了大众的视野。细数这四十几年&#xff0c;OA办公系统已经由一个异想天开的想法变成…

centos7.8离线安装pg和postgis

安装包下载地址&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1MxJc-5Ws6OPTRAoC-2srJw 提取码&#xff1a;is2q 1.centos7.8 离线安装pg操作步骤 这里基于centos7.8空白系统操作实践写的文档&#xff0c;系统一致的情况下可以照搬教程操作安装&#xff0c;镜像为…

1.0、Hibernate-快速入门初体验

1.0、Hibernate-快速入门初体验 Hibernate 和 mybatis 一样是 ORM (Object Relation Mapping) 对象关系映射框架&#xff0c;将面向对象映射成面向关系。 如何使用呢&#xff1f; 1、导入依赖&#xff1b; 2、创建 Hibernate 配置文件&#xff1b; 3、创建实体类&#xff1b; 4…

Allegro172版本多人协同在线设计操作指导

Allegro172版本多人协同在线设计操作指导 Allegro升级到172版本,可以支持多人协同设计,并且实时同步,具体操作如下 首先用户需要在同一个局域网下,并且Allegro172的版本必须一致,比如都是S082的版本 第一个用户打开PCB,选择Symphony Team design 选择 Start Symphony …

2022年度总结

自我介绍 大家好&#xff0c;我又回来了&#xff01;我在一年之前在 CSDN 写了第一篇文章&#xff0c;到现在也有一年时间了。这次回来呢&#xff0c;也是因为 CSDN 官方发的消息&#xff0c;让写一篇年度总结的文章。在离开的这几个月里&#xff0c;主要是因为工作繁忙&#…

ASO优化:总结APP被下架的5点原因

随着苹果的App Store的监管力度的不断加强&#xff0c;每个APP都会有被下架的风险&#xff0c;而对于开发者来说&#xff0c;APP被下架是一件很严重的事情&#xff0c;不仅会造成用户的流失&#xff0c;还会降低用户对APP 的信任。所以&#xff0c;我们要了解APP被下架的原因&a…

【大数据技术Spark】Spark SQL操作Dataframe、读写MySQL、Hive数据库实战(附源码)

需要源码和依赖请点赞关注收藏后评论区留言私信~~~ 一、Dataframe操作 步骤如下 1&#xff09;利用IntelliJ IDEA新建一个maven工程&#xff0c;界面如下 2&#xff09;修改pom.XML添加相关依赖包 3&#xff09;在工程名处点右键&#xff0c;选择Open Module Settings 4&a…

整数的大小端序

在存储整数时&#xff0c;一般按字节为逻辑单位进行存储&#xff0c;有“小端序”和“大端序”之分。小端序&#xff08;little-endian&#xff09; 是指将表示整数的低位字节存储在内存地址的低位&#xff0c;高位字节存储在内存地址的高位。如果将整数 1982062410 存储至内存…

【CANN训练营第三季】2022年度第三季新手班之昇腾AI入门课

本次参加CANN训练营&#xff0c;本来我报名的是进阶班课程&#xff0c;再看一遍新手班&#xff0c;学习一下目前CANN的最新进展也是不错的&#xff0c;巩固一下。 视频课程大家可以从这里看到 &#xff08;1&#xff09;【CANN训练营第三季】- 昇腾AI入门课&#xff08;上&am…

使用Keepalived工具实现集群节点的高可用

GreatSQL社区原创内容未经授权不得随意使用&#xff0c;转载请联系小编并注明来源。GreatSQL是MySQL的国产分支版本&#xff0c;使用上与MySQL一致。作者&#xff1a;蟹黄瓜子文章来源&#xff1a;社区投稿 1.前言 在集群当中离不开的一个词就是是高可用&#xff0c;用本文来…

OpenWrt + 每步科技DDNS 实现ipv6动态域名解析方法

其实好几个月前我就已经把这个动态域名设置好了&#xff0c;后面重新刷了系统&#xff0c;忘记保存&#xff0c;又得重新再来&#xff0c;这次把过程记录一下&#xff0c;免得下次再从头百度。 工具 刷好openWrt的路由器一个每步科技注册的域名&#xff08;我为什么选择这个&…

数字电子技术(八)D/A和A/D转换

D/A和A/D转换概述D/A转换A/D转换例题练习模拟信号&#xff1a;在时间与数值上都连续 数字信号&#xff1a;在时间与数值上都离散 概述 D/A转换&#xff1a;数字信号——模拟信号 &#xff08;D/A转换器简称DAC&#xff09;A/D转换&#xff1a;模拟信号——数字信号 &#xff0…

修改物料编号格式及长度

修改物料编号格式及长度(OMSL) 路径&#xff1a;IMG--后勤常规--物料主数据--基本设置--定义物料编号的输出格式

毕业设计 - 基于JSP的合同信息管理系统【源码+论文】

文章目录前言一、项目设计1. 模块设计数据库设计2. 实现效果二、部分源码项目源码前言 今天学长向大家分享一个 java web jsp 项目: 基于JSP的合同信息管理系统 适合用于毕业设计、课程设计 一、项目设计 1. 模块设计 需求分析是从客户的需求中提取出软件系统能够帮助用户…

java互联网医院系统HIS源码带本地搭建教程

技术架构 技术框架&#xff1a;SpringBoot MySql MyBatis nginx Vue2.6 原生APP 运行环境&#xff1a;jdk8 IntelliJ IDEA maven 宝塔面板 Android Studio 文字本地搭建教程 下载源码&#xff0c;小皮面板安装mysql5.7数据库&#xff0c;创建一个新数据库&#xff0c;…

引力波探测,冷冻电镜研究:两项诺奖GPU功不可没

我们的日常工作固然重要&#xff0c;但并非每一份重要的工作都能够助力他人获得诺贝尔奖。然而&#xff0c;就在2017年10月&#xff0c;GPU 计算便两度成为了助力获得诺贝尔奖的幕后英雄。 三名美国物理学家Rainer Weiss、Barry Barish和Kip Thorne因探测到了爱因斯坦百年前预测…

从“跨域融合”到“中央计算”,这家Tier1如何率先抢跑?

全球汽车产业已经进入以智能化为主旋律的下半场竞赛&#xff0c;同时整车电子电气架构也在加速跨入集中式电子电气架构时代。 在这样的背景之下&#xff0c;智能驾驶域控制器成为了当前最大的增量市场之一&#xff0c;由此也带动了上游芯片、OS、中间件等域控相关软硬件产品的…