Linux内核里的DebugFS

2023-05-16



DebugFS,顾名思义,是一种用于内核调试的虚拟文件系统,内核开发者通过debugfs和用户空间交换数据。类似的虚拟文件系统还有procfs和sysfs等,这几种虚拟文件系统都并不实际存储在硬盘上,而是Linux内核运行起来后才建立起来。

通常情况下,最常用的内核调试手段是printk。但printk并不是所有情况都好用,比如打印的数据可能过多,我们真正关心的数据在大量的输出里不是那么一目了然;或者我们在调试时可能需要修改某些内核变量,这种情况下printk就无能为力,而如果为了修改某个值重新编译内核或者驱动又过于低效,此时就需要一个临时的文件系统可以把我们需要关心的数据映射到用户空间。在过去,procfs可以实现这个目的,到了2.6时代,新引入的sysfs也同样可以实现,但不论是procfs或是sysfs,用它们来实现某些debug的需求,似乎偏离了它们创建的本意。比如procfs,其目的是反映进程的状态信息;而sysfs主要用于Linux设备模型。不论是procfs或是sysfs的接口应该保持相对稳定,因为用户态程序很可能会依赖它们。当然,如果我们只是临时借用procfs或者sysfs来作debug之用,在代码发布之前将相关调试代码删除也无不可。但如果相关的调试借口要在相当长的一段时间内存在于内核之中,就不太适合放在procfs和sysfs里了。故此,debugfs应运而生。

默认情况下,debugfs会被挂载在目录/sys/kernel/debug之下,如果您的发行版里没有自动挂载,可以用如下命令手动完成:

# mount -t debugfs none /your/debugfs/dir

Linux内核为debugfs提供了非常简洁的API,本文接下来将以一个实作为例来介绍,sample code可以从这里下载。

这个实作会在debugfs中建立如下的目录结构:

其中,a对应模块中的一个u8类型的变量,b和subdir下面的c都是对应模块里的一个字符数组,只是它们的实现方式不同。

在module_init里,我们首先要建立根目录mydebug:

1
my_debugfs_root = debugfs_create_dir( "mydebug" , NULL);

第一个参数是目录的名称,第二个参数用来指定这个目录的上级目录,如果是NULL,则表示是放在debugfs的根目录里。

子目录也是用debugfs_create_dir来实现:

1
sub_dir = debugfs_create_dir( "subdir" , my_debugfs_root);

建立文件a的代码非常简单:

1
debugfs_create_u8( "a" , 0644, my_debugfs_root, &a);

这表示文件名为“a”,文件属性是0644,父目录是上面建立的“mydebug”,对应的变量是模块中的a。

Linux内核还提供了其他一些创建debugfs文件的API,请参考本文的附录。

b是一个32-bytes的字符数组,在debugfs里,数组可以用blob wrapper来实现。

1
2
3
4
5
6
char hello[32] = "Hello world!\n" ;
struct debugfs_blob_wrapper b;
 
b.data = ( void *)hello;
b.size = strlen (hello) + 1;
debugfs_create_blob( "b" , 0644, my_debugfs_root, &b);

这里需要注意的是,blob wrapper定义的数据只能是只读的。在本例中,虽然我们把文件b的权限设定为0644,但实际这个文件还是只读的,如果试图改写这个文件,系统将提示出错。

如果需要对内核数组进行写的动作,blob wrapper就无法满足要求,我们只能通过自己定义文件操作来实现。在这个实作里,可以参考文件c的实现。c和b在模块里对应着同一块字符数组,不同的是,b是只读的,而c通过自定义的文件操作同时实现了读和写。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
static int c_open( struct inode *inode, struct file *filp)
{
     filp->private_data = inode->i_private;
     return 0;
}
 
static ssize_t c_read( struct file *filp, char __user *buffer,
         size_t count, loff_t *ppos)
{
     if (*ppos >= 32)
         return 0;
     if (*ppos + count > 32)
         count = 32 - *ppos;
 
     if (copy_to_user(buffer, hello + *ppos, count))
         return -EFAULT;
 
     *ppos += count;
 
     return count;
}
 
static ssize_t c_write( struct file *filp, const char __user *buffer,
         size_t count, loff_t *ppos)
{
     if (*ppos >= 32)
         return 0;
     if (*ppos + count > 32)
         count = 32 - *ppos;
 
     if (copy_from_user(hello + *ppos, buffer, count))
         return -EFAULT;
 
     *ppos += count;
 
     return count;
}
 
struct file_operations c_fops = {
     .owner = THIS_MODULE,
     .open = c_open,
     .read = c_read,
     .write = c_write,
};
 
 
debugfs_create_file( "c" , 0644, sub_dir, NULL, &c_fops);

注:代码里,c_open其实并没有任何用处,因为c_read和c_write直接引用了全局变量hello。这里,我们也可以换一种写法,在read/write函数里用filp->private_data来引用字符数组hello。

到这里,三个文件和子目录已经创建完毕。在module_exit中,我们要记得释放创建的数据。

1
debugfs_remove_recursive(my_debugfs_root);

debugfs_remove_recursive可以帮我们逐步移除每个分配的dentry,如果您想一个一个手动的移除,也可以直接调用debugfs_remove。

 

附录:

创建和撤销目录及文件

1
2
3
4
5
6
struct dentry *debugfs_create_dir( const char *name, struct dentry *parent);
struct dentry *debugfs_create_file( const char *name, mode_t mode,
         struct dentry *parent, void *data,
         const struct file_operations *fops);
void debugfs_remove( struct dentry *dentry);
void debugfs_remove_recursive( struct dentry *dentry);

创建单值文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
struct dentry *debugfs_create_u8( const char *name, mode_t mode,
         struct dentry *parent, u8 *value);
struct dentry *debugfs_create_u16( const char *name, mode_t mode,
         struct dentry *parent, u16 *value);
struct dentry *debugfs_create_u32( const char *name, mode_t mode,
         struct dentry *parent, u32 *value);
struct dentry *debugfs_create_u64( const char *name, mode_t mode,
         struct dentry *parent, u64 *value);
 
struct dentry *debugfs_create_x8( const char *name, mode_t mode,
         struct dentry *parent, u8 *value);
struct dentry *debugfs_create_x16( const char *name, mode_t mode,
         struct dentry *parent, u16 *value);
struct dentry *debugfs_create_x32( const char *name, mode_t mode,
         struct dentry *parent, u32 *value);
 
struct dentry *debugfs_create_size_t( const char *name, mode_t mode,
         struct dentry *parent, size_t *value);
struct dentry *debugfs_create_bool( const char *name, mode_t mode,
         struct dentry *parent, u32 *value);

其中,后缀为x8、x16、x32的这三个函数是指debugfs中的数据用十六进制表示。

创建BLOB文件

1
2
3
4
5
6
7
struct debugfs_blob_wrapper {
     void *data;
     unsigned long size;
};
 
struct dentry *debugfs_create_blob( const char *name, mode_t mode,
          struct dentry *parent, struct debugfs_blob_wrapper *blob);

其它

1
2
3
4
5
struct dentry *debugfs_rename( struct dentry *old_dir, struct dentry *old_dentry,
         struct dentry *new_dir, const char *new_name);
 
struct dentry *debugfs_create_symlink( const char *name,
         struct dentry *parent, const char *target);

 


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Linux内核里的DebugFS 的相关文章

  • C++11带来的lambda表达式

    C 43 43 11带来了lambda表达式 xff0c 可以简化程序的编写 xff0c 使代码更加清晰 现在按照步骤来介绍lambda表达式 xff1a 1 函数对象 又叫仿函数 xff0c 如果一个类或者结构体重载了operator 操
  • caffe中几个基本概念

    caffe中几个基本概念 1 caffe中的blob结构是用来进行数据存储 交换和处理网络中正向反向迭代时的数据和导数信息的数据结构 blob是caffe的标准数组结构 他提供了一个统一的内存接口 其将内部的cpu gpu数据之间的传输与存
  • 摄像头引脚定义

    摄像头引脚定义 1 NC NO CONNECT 2 AGND Power Analog ground 3 SIO D I O SCCB serial interface data I O 4 AVDD Power Analog power
  • Android7.0 JACK编译器不支持多用户同时编译的问题的解决

    xfeff xfeff Android7 0 xff08 也就是Android N xff09 上默认使用JACK编译器而不再使用openjdk了 xff0c 但发现JACK不是很好用 xff0c 比如最大的一个问题就是 xff0c 同一台
  • 【树莓派】死机自动重启、掉线自动重连

    目录 WIFI掉线自动重连 首先查看你的板子硬件型号 拿树莓派去做服务器就要配置下这两项 xff0c 保证随时能够VNC控制 WIFI掉线自动重连 http shumeipai nxez com 2017 01 25 raspberry p
  • open vswitch分析

    Open vSwitch 概述 Open vSwitch xff08 下面简称 OVS xff09 是一个高质量的 多层虚拟交换机 OVS 遵循开源 Apache2 0 许可 xff0c 通过可编程扩展 xff0c OVS 可以实现大规模网
  • C# 接口《通俗解释》

    原文地址 xff1a https www cnblogs com hamburger p 4681681 html 接口的定义 xff1a 接口是指定一组函数成员 xff0c 而不实现他们的引用类型 接口使用interface 关键字进行定
  • linux 如何查看指定动态库

    要查看 Linux 系统指定的动态库 xff0c 可以使用以下命令 xff1a 使用 ldconfig 命令 xff1a ldconfig p 该命令将显示系统已加载的所有动态库及其路径 如果要查找特定动态库 xff0c 可以使用 grep
  • Tortoisegit 恢复文件夹被删除的文件(被误删)

    关于Tortoisegit 恢复git文件夹中被删除的文件 xff1a 1 在git文件夹右键tortorisegit show log 2 选择版本 xff08 当时执行删除操作的版本 xff09 3 选择被delete掉的 xff0c
  • putty screen 快捷键

    使用putty的时候 xff0c 开启screen再detach xff0c 可以防止跑程序过程中断开连接而导致程序中断 总结了下putty与screen 相关的快捷键 目前常用的有如下几个 xff08 命令均在putty终端输入 xff0
  • Magento的不同版本(CE,EE,ECE)介绍

    Magento提供了三个不同的版本平台 xff0c 即Magento Community Edition xff08 CE xff09 社区版 xff0c Magento Enterprise Edition xff08 EE xff09
  • c语言初学,字母大小写转换

    这类题目主要通过ASCII码差值实现 xff0c A对应ASCII码十进制数字是65 xff0c a对应ASCII码十进制数字是97 xff0c 即大小写字母之间ASCII码差值为32 xff0c 想要将大写字母转换为小写字母可以将该字符A
  • matlab——subplot多子图共用一个colorbar,微调子图和colorbar位置

    用subplot命令画出多个图后 xff0c 需要让这些图共用一个colorbar 在这里与大家分享我的操作 xff0c 希望能帮助到有需要的人 备注 xff1a 从 R2019b 开始 xff0c 可以在分块图布局中显示共享颜色栏 xff
  • 远程连接服务器数据库报错:Host ‘XXXXXX’ is blocked because of many connection errors

    一 我遇到的问题描述 使用Navicat for mysql连接公司的服务器数据库 xff0c 报错 xff1a Host XXXXXX is blocked because of many connection errors 二 出现错误
  • android中MediaCodec硬编码中关键帧间隔时间设置问题

    在MediaCodec硬编码中设置 xff29 关键帧时间间隔 xff0c 在 xff21 xff30 xff29 中是这么设置的 mMediaCodec 61 MediaCodec createByCodecName debugger g
  • python3 网络编程问题——虚拟机centos7上运行tcp服务器,在主机win10上使用网络调试助手作为tcp客户端无法建立连接,提示1035错误:the socket is marked...

    前提 xff1a 主机和虚拟机都是在同一网段下 我的网络调试助手的连接结果如下图 xff1a 注意 红框中的提示 xff0c 连接超时的结果可能是由于以下两种可能的情况导致的 xff1a 1 服务器端口未开启监听 2 路由项被防火墙拦截 对
  • DSSM pytorch实现

    之前在网上找到了一个文本匹配实现仓库 xff0c 但是没有提供DSSM的代码 xff0c 我就根据那个代码实现以下DSSM 数据集采用的是蚂蚁金服的数据集 也参考过别人的代码 xff0c 但是总感觉怪怪的 xff0c DSSM原文中 xff
  • 文本匹配实验结果总结

    主要把一些实验结果说一下 xff1a DSSM 作为文本匹配的开山鼻祖 xff0c 想法也很简单 xff0c 就是将query 和doc拉到同一维度 xff0c 然后计算余弦相似度 xff0c 网络也是非常简单 xff0c 所以只获得了78
  • 使用wikiextractor 提取wiki数据

    wikiextractor包链接地址 xff1a https github com attardi wikiextractor 安装wikiextractor pip install wikiextractor 然后下载wiki语料库 xf
  • python爬虫(Python读取TXT文件中的URL并下载文件)

    前言 xff1a 本人之前并没有接触过python爬虫 xff0c 但是现在因为要做个试验 xff0c 需要下载海量人脸图片 xff0c 所以需要用到python爬虫这个办法 但是过程中遇到到了很多问题 xff0c 程序调了很久都不成功 x

随机推荐

  • 机器学习之python读取CSV文件

    当我们在用python处理机器学习的问题时 xff0c 往往需要先读取数据 xff0c 这些数据通常都是文件 xff0c 我今天遇到的是CSV文件 xff0c 是在kaggle竞赛数据集下载的 xff08 比如手写数字识别 xff0c 以及
  • Robust PCA Low-rank(附matalb 代码)

    最近在看的论文中 xff0c 包括人脸识别 xff0c 以及深度神经网络模型压缩等论文中 xff0c 都会有low rank 低秩 低秩稀疏分解等解决方法 xff0c 感觉关于low rank的研究还挺火的 xff0c 这个问题和Robus
  • 完美图解教程 Linux环境VNC服务安装、配置与使用

    图片直观明了 xff0c 尝试一步一步分享俺的成果 1 xff1a 下面第一步当然是确认自己linux系统是否安装VNC 默认情况下 xff0c Red Hat Enterprise Linux安装程序会将VNC服务安装在系统上 打开终端窗
  • torch.ge,torch.gt,torch.le

    torch ge torch ge input other out 61 None Tensor 逐元素比较input和other xff0c 即是否 input gt 61 otherinput gt 61 other 如果两个张量有相同
  • VAE(变分自动编码器)

    首先先贴上一些有用的链接 xff1a https www cnblogs com king lps p 8477300 html https zhuanlan zhihu com p 29685634 再补充一个链接 xff1a https
  • 视频去噪资料整理(深度学习方法)

    近几天做了一些视频去噪的一些边缘工作 xff0c 故整理一下 我读的一篇论文 xff1a paper TOFlow Video Enhancement with Task Oriented Flow code https github co
  • 正则表达式里的?:是啥意思例如(?:a|b)

    我也是找答案时看到的 xff0c 发现这里回答的理论是的 xff0c 但不好让人理解 xff0c 我也结合其他地方的资料 xff0c 才能理解他的答案 下面我用两个例子来说明 单引号里面的三个元字符之间的意思 39 39 1 39 39 x
  • idea设置javadoc、idea2020单行注释的快捷键

    找了半天 xff0c 想不起来叫什么 1 其实就是给方法和类上添加这种doc文档的注释的快捷键 xff1a 打开setting keymap 搜索 xff1a fix doc comment 我习惯用ctrl 43 enter 2 切换到i
  • LaTeX分享008【LaTeX多图排列方法】

    LaTeX分享 LaTeX多图排列方法 作者 xff1a JinyuLi 日期 xff1a 2023 03 18 内容 xff1a 填坑 xff0c 补充上一篇专栏中LaTeX图片插入问题中的多张图片同时插入的实现方法部分 xff0c 本篇
  • SONiC(2):手动运行sonic-vs

    SONiC的testbed都是用ansible自动部署的 xff0c 下面尝试手动来创建 另外最新的sonic vs可以从这里下载 准备工作 ansible生成的vlab 01这个虚机的vir配置xml文件如下 testbed 64 u18
  • SONiC vs testbed搭建

    准备工作 一台安装Ubuntu18 04的系统 xff0c 内存建议不少于16G 需要支持kvm虚拟化安装ssh server sudo apt update y sudo apt openssh server y 设置sudo免密 sud
  • 2. 安装GNOME和KDE图形化桌面

    安装GNOME和KDE图形化桌面 1 使用CD DVD介质配置本地Yum源2 安装GNOME图形化桌面2 1 安装GNOME xff1a 2 2 设置在系统启动时进入图形化桌面3 安装KDE图形化桌面3 1 安装KDE xff1a 3 2
  • 复位电路的几种设计

    本人转自 xff1a http hi baidu com yinweini2 item 48ba4f12f54587711009b591 复位源是导致单片机内部复位操作的源泉 xff0c 大致可分为七种 xff1a 上电复位 xff08 P
  • Hadoop入门经典:WordCount

    以下程序在hadoop1 2 1上测试成功 本例先将源代码呈现 xff0c 然后详细说明执行步骤 xff0c 最后对源代码及执行过程进行分析 一 源代码 package org jediael hadoopdemo wordcount im
  • Jlink 采用 SWD 模式下载电路接法

    在Jlink上 xff1a 对应的电路图为 xff1a 其中要使用的是 Pin1 gt vcc Pin7 gt SWDIO Pin9 gt SWCLK Pin4 gt GND 其他GND 引脚也可 在对于的开发板 xff08 举例 xff1
  • ubuntu系统硬盘温度过高的解决方法

    一 更改swap分区设置 在ubuntu 里面 xff0c swappiness的值的大小对如何使用swap分区是有着很大的联系的 swappiness 61 0的时候表示最大限度使用物理内存 xff0c 然后才是 swap空间 xff0c
  • MBus协议详解(一)

    看了许多关于MBus协议的资料 xff0c 感觉说的不具体 不完整 也不系统 xff0c 本人准备结合一个具体的产品实现 xff0c 从理论和实现上对MBus协议做一个详细的论述 xff0c 如有不当之处 xff0c 欢迎讨论 1 介绍 M
  • MBus协议详解(二)

    4 4 slave 设计 传输特性 xff1a slaves 被设计为具有两种不同恒定 sink 电流 xff0c 因此在总线上电压有 1V 的变化的时候 xff0c sink 电流的变化一定不能超过 0 2 为了传输一个 Mark xff
  • 多个进程对同一文件写入的问题

    转载 讨论关于并发环境下 xff0c 多个进程对同一文件写入的问题 xff0c 我们会涉及到文件共享的知识 在开始之前 xff0c 我们先讨论一些有关文件共享的知识 1 文件共享 Unix系统支持在不同进程间共享打开的文件 为此 xff0c
  • Linux内核里的DebugFS

    DebugFS xff0c 顾名思义 xff0c 是一种用于内核调试的虚拟文件系统 xff0c 内核开发者通过debugfs和用户空间交换数据 类似的虚拟文件系统还有procfs和sysfs等 xff0c 这几种虚拟文件系统都并不实际存储在