Linux下的Debugfs
debugfs
1. 简介
类似sysfs、procfs,debugfs 也是一种内存文件系统。不过不同于sysfs一个kobject对应一个文件,procfs和进程相关的特性,debugfs的灵活度很大,可以根据需求对指定的变量进行导出并提供读写接口。debugfs又是一个Linux中 everything is a file 哲学的体现,通过VFS实现了对驱动的控制。可以通过以下命令,来挂载debugfs到指定目录。
Debugfs其存在的主要意义是为了内核开发者向用户空间传递更多有用的信息,与proc不同,proc只提供进程相关的信息;同时也与sysfs不同,sysfs对每个文件都要求一定的规则,而Debugfs没有任何的规则。
简而言之,Debugfs是一种用于内核调试的虚拟文件系统。
用途:将内核程序中的变量以文件的形式直观的展现出来,并可以直接通过文件操作来读取或修改内核变量的值,便于开发调试
2. 食用方式
1. 内核使能Debudfs
在menuconfig中使能DEBUG_FS = y

2.挂载命令
mount -t debugfs none /sys/kernel/debug
3.内核接口
1. API接口
- 想要使用Debugfs功能,首先要做的就是要包含
<linux/debugfs.h>头文件 - 使用
debugfs_create_dir接口,创建一个文件夹,用于保存debugfs所操作的文件 - 使用
debugfs_create_file接口,创建多个文件进行操作
2. API介绍
1. debugfs_create_dir
struct dentry *debugfs_create_dir(const char *name, struct dentry *parent);
| 参数 | 作用 | 备注 |
|---|---|---|
| name | 文件夹名称 | |
| parent | 父目录 | 如果为NULL,则在/sys/kernel/debug目录下 |
| dentry | 返回值 | 表示创建的 debugfs 文件(或目录)的 dentry 节点。如果文件创建成功,它返回一个有效的 dentry 指针;如果创建失败,则返回 NULL。 |
2. debugfs_create_file
struct dentry *debugfs_create_file(const char *name, umode_t mode,struct dentry *parent, void *data,const struct file_operations *fops);
| 参数 | 作用 | 备注 |
|---|---|---|
| name | 文件名称 | |
| mode | 文件访问权限 | 可以是整型(比如0644)也可以使用内核的宏 |
| parent | 父目录,用于保存该文件 | 如果为空则该文件的父目录为根目录 |
| data | 文件操作的私有数据 | inode的i_private字段指向这个结构 |
| fops | 文件的自定义操作 | 可以自定义所有操作接口,也可以使用宏DEFINE_SIMPLE_ATTRIBUTE指定读写操作即可 |
DEFINE_SIMPLE_ATTRIBUTE宏:
//
// __get: 读操作 int (*get)(void *data, u64 *value),👇
//bash下cat file ,回显内容便是内核层传给应用层的*value的值
// __set: 写操作 int (*set)(void *data, u64 value),👇
//bahs下echo 1 > file , value的值便是应用层传入内核层的数据1
// __fmt: 用于指定 get 和 set 函数的输入输出格式。 const char *fmt👇
//例如,它可以定义一个整数、浮点数或字符串的格式,以便在 sysfs 读写操作接口中正确显示或解析值。
#define DEFINE_SIMPLE_ATTRIBUTE(__fops, __get, __set, __fmt) \
static int __fops ## _open(struct inode *inode, struct file *file) \
{ \__simple_attr_check_format(__fmt, 0ull); \return simple_attr_open(inode, file, __get, __set, __fmt); \
} \
3. debugfs_create_u8
void debugfs_create_u8(const char *name, umode_t mode,struct dentry *parent, u8 *value);
| 参数 | 作用 | 备注 |
|---|---|---|
| name | 文件名 | 一般以变量名来命名,方便调试 |
| mode | 文件权限 | |
| parent | 父目录 | |
| value | 变量 | 变量的值会被存在文件内 |
其他变量类型的接口:👇
//创建十进制的无符号文件
void debugfs_create_u8(const char *name, umode_t mode,struct dentry *parent, u8 *value);
void debugfs_create_u16(const char *name, umode_t mode,struct dentry *parent, u16 *value);
void debugfs_create_u32(const char *name, umode_t mode,struct dentry *parent, u32 *value);
void debugfs_create_u64(const char *name, umode_t mode,struct dentry *parent, u64 *value);
//创建十六进制的无符号文件
void debugfs_create_x8(const char *name, umode_t mode,struct dentry *parent, u8 *value);
void debugfs_create_x16(const char *name, umode_t mode,struct dentry *parent, u16 *value);
void debugfs_create_x32(const char *name, umode_t mode,struct dentry *parent, u32 *value);
void debugfs_create_x64(const char *name, umode_t mode,struct dentry *parent, u64 *value);//创建一个size_t类型的文件
void debugfs_create_size_t(const char *name, umode_t mode,struct dentry *parent, size_t *value);
//创建一个unsigned long类型的文件
struct dentry *debugfs_create_ulong(const char *name, umode_t mode,struct dentry *parent,unsigned long *value);
//创建一个十六进制的unsigned long类型的文件
void debugfs_create_xul(const char *name, umode_t mode,struct dentry *parent, unsigned long *value);
// 布尔型
void debugfs_create_bool(const char *name, umode_t mode,struct dentry *parent, bool *value);
Deme one
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/debugfs.h>static struct dentry *dir = NULL;static unsigned int debugfs_hello;static u32 sum = 0;static int add_write(void *data, u64 value)
{sum += value;return 0;
}
// 文件操作变量名,get读操作,set写操作,将读写操作的返回值以字符串格式化的形式读出或写入文件内部
DEFINE_SIMPLE_ATTRIBUTE(add_ops, NULL, add_write, "%llu\n");static __init int hello_init(void)
{struct dentry *tmp_dir = NULL;/* create /sys/kernel/debug/debugfs_hello/ directory */dir = debugfs_create_dir("debugfs_hello", NULL);if (!dir) {printk(KERN_ALERT "debugfs_create_dir failed\n");return -1;}/* create /sys/kernel/debug/debugfs_hello/hello value, mode: rw*/tmp_dir = debugfs_create_u32("hello", 00666, dir, &debugfs_hello);if (!tmp_dir) {printk(KERN_ALERT "debugfs_create_u32 failed\n");return -1;}/* create /sys/kernel/debug/debugfs_hello/add value, mode: w*/tmp_dir = debugfs_create_file("add", 0222, dir, NULL, &add_ops);if (!tmp_dir) {printk(KERN_ALERT "debugfs_create_file failed\n");return -1;}/* create /sys/kernel/debug/debugfs_hello/sum value, mode: r*/tmp_dir = debugfs_create_u32("sum", 0444, dir, &sum);if (!tmp_dir) {printk(KERN_ALERT "debugfs_create_u32 failed\n");return -1;}return 0;
}static void __exit hello_exit(void)
{printk(KERN_INFO "Exit debugfs_hello module\n");debugfs_remove_recursive(dir);dir = NULL;
}module_init(hello_init);
module_exit(hello_exit);MODULE_LICENSE("GPL");
Demo TWO
#include <linux/debugfs.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/errno.h>
#include <linux/dcache.h>
#include <linux/types.h>static char zen_buf[512] = "hello\n";
static struct dentry *zen_dir;static int zen_open(struct inode *inode, struct file *filp)
{printk("zen open\n");filp->private_data = inode->i_private;return 0;
}ssize_t zen_read(struct file *filp, char __user *buf, size_t count, loff_t *offp)
{int retval = 0;if ((*offp + count) > 512)count = 512 - *offp;printk("read request: count:%u, offset:%u\n", count, *offp);if (copy_to_user(buf, zen_buf+*offp, count)) {printk("copy to user failed, count:%ld\n", count);retval = -EFAULT;goto out;}*offp += count;retval = count;
out:return retval;
}ssize_t zen_write(struct file *filp, const char __user *buff, size_t count, loff_t *offp)
{int retval;printk("write request: count:%u, offset:%u\n", count, *offp);if (*offp > 512)return 0;if (*offp + count > 512)count = 512 - *offp;if (copy_from_user(zen_buf+*offp, buff, count)) {printk("copy from user failed, count:%ld\n", count);retval = -EFAULT;goto out;}*offp += count;retval = count;
out:return retval;
}struct file_operations my_fops = {.owner = THIS_MODULE,.read = zen_read,.write = zen_write,.open = zen_open,
};static int __init debugfs_init(void)
{printk("INIT MODULE\n");zen_dir = debugfs_create_dir("zen_dir4", NULL);if (!zen_dir) {printk("zen_dir4 is null\n");goto fail;}static struct dentry *sub_zen_dir;sub_zen_dir = debugfs_create_dir("sub_zen", zen_dir);if (!sub_zen_dir) {printk("sub zen dir is null\n");goto fail;}struct dentry *filent = debugfs_create_file("zen", 0644, sub_zen_dir, NULL, &my_fops);if (!filent) {printk("zen file is null\n");goto fail;}printk("INIT SUCCESS\n");return 0;
fail:
//return -ENOENT;return -1;
}static void __exit debugfs_exit(void)
{printk("exit module\n");debugfs_remove_recursive(zen_dir);printk("exit success\n");
}module_init(debugfs_init);
module_exit(debugfs_exit);
MODULE_LICENSE("GPL");
4. 加载模块
编译完后生成的.ko文件,使用insmod加载进内核,即可在/sys/kernel/debug下看到生成目录及文件
相关文章:
Linux下的Debugfs
debugfs 1. 简介 类似sysfs、procfs,debugfs 也是一种内存文件系统。不过不同于sysfs一个kobject对应一个文件,procfs和进程相关的特性,debugfs的灵活度很大,可以根据需求对指定的变量进行导出并提供读写接口。debugfs又是一个Li…...
【FFmpeg】调整音频文件的音量
1、调整音量的命令 1)音量调整为当前音量的十倍 ffmpeg -i inputfile -vol 1000 outputfile 2)音量调整为当前音量的一半 ffmpeg -i input.wav -filter:a "volume=0.5" output.wav3)静音 ffmpeg -i input.wav -filter:a "volume=0" output.wav4)…...
mac 打开访达快捷键
一、使用快捷键组合 1. Command N 在当前桌面或应用程序窗口中,按下“Command N”组合键可以快速打开一个新的访达窗口。这就像在 Windows 系统中通过“Ctrl N”打开新的资源管理器窗口一样。 2. Command Tab 切换 如果访达已经打开,只是被其他应…...
Ubuntu学习笔记 - Day2
文章目录 学习目标:学习内容:学习笔记:Linux系统启动过程内核引导运行init运行级别系统初始化建立终端用户登录系统 Ubuntu关机关机流程相关命令 Linux系统目录结构查看目录目录结构 文件基本属性读写权限命令 下载文件的方法安装wget工具下载…...
c++基础12比较/逻辑运算符
比较/逻辑运算符 布尔比较运算符逻辑运算符位运算符(也用于逻辑运算)1<a<10怎么表达T140399判断是否为两位数代码 布尔 在C中,布尔类型是一种基本数据类型,用于表示逻辑值,即真(true)或假…...
mac-ubuntu虚拟机(扩容-共享-vmtools)
一、磁盘扩容 使用GParted工具对Linux磁盘空间进行扩展 https://blog.csdn.net/Time_Waxk/article/details/105675468 经过上面的方式后还不够,需要再进行下面的操作 lvextend 用于扩展逻辑卷的大小,-l 选项允许指定大小。resize2fs 用于调整文件系统的…...
数学建模学习(135):使用Python基于WSM、WPM、WASPAS的多准则决策分析
1. 算法介绍 多标准决策分析(Multi-Criteria Decision Analysis, MCDA)是帮助决策者在复杂环境下做出合理选择的重要工具。WSM(加权和法)、WPM(加权乘积法)、WASPAS(加权和乘积评估法)是 MCDA 中的三种常用算法。它们广泛应用于工程、经济、供应链管理等多个领域,用于…...
VScode的C/C++点击转到定义,不是跳转定义而是跳转声明怎么办?(内附详细做法)
以最简单的以原子的跑马灯为例: 1、点击CtrlShiftP,输入setting,然后回车 2、输入Browse 3、点击下面C_Cpp > Default > Browse:Path里面添加你的工程路径 然后就可以愉快地跳转定义啦~ 希望对你有帮助,如果还不可以的话&a…...
设备管理网关(golang版本)
硬件设备:移远EC200A-CN LTE Cat 4 无线通信模块 操作系统:openwrt 技术选型:layui golang sqlite websocket 工程结构 界面展示 区域管理 设备管理 运行监控 系统参数 资源文件 版本信息...
Armv8的安全启动
目录 1. Trust Firmware 2. TF-A启动流程 3. TF-M启动流程 3.1 BL1 3.2 BL2 4.小结 在之前汽车信息安全 -- 再谈车规MCU的安全启动文章里,我们详细描述了TC3xx 、RH850、NXPS32K3的安全启动流程,而在车控类ECU中,我们也基本按照这个流程…...
冒泡排序、选择排序、计数排序、插入排序、快速排序、堆排序、归并排序JAVA实现
常见排序算法实现 冒泡排序、选择排序、计数排序、插入排序、快速排序、堆排序、归并排序JAVA实现 文章目录 常见排序算法实现冒泡排序选择排序计数排序插入排序快速排序堆排序归并排序 冒泡排序 冒泡排序算法,对给定的整数数组进行升序排序。冒泡排序是一种简单…...
SQL CASE表达式与窗口函数
CASE 表达式是一种通用的条件表达式,类似于其他编程语言中的if/else语句。 窗口函数类似于group by,但是不会改变记录行数,能扫描所有行,能对每一行执行聚合计算或其他复杂计算,并把结果填到每一行中。 1 CASE 表达式…...
基于SpringBoot的植物园管理小程序【附源码】
基于SpringBoot的植物园管理小程序 效果如下: 系统登录页面 管理员主页面 商品订单管理页面 植物园信息管理页面 小程序主页面 小程序登录页面 植物信息查询推荐页面 研究背景 随着互联网技术的快速发展和移动设备的普及,线上管理已经成为各行各业提高…...
asp.net网站项目如何设置定时器,定时获取数据
在 Global.asax.cs 文件中编写代码来初始化和启动定时器。Global.asax.cs 文件定义了应用程序全局事件,比如应用程序的启动和结束。在这里,我们将在应用程序启动时初始化和启动定时器。 using System; using System.Timers;public class Global : Syste…...
单元/集成测试解决方案
在项目开发的前期针对软件单元/模块功能开展单元/集成测试,可以尽早地发现软件Bug,避免将Bug带入系统测试阶段,有效地降低HIL测试的测试周期,也能有效降低开发成本。单元/集成测试旨在证明被测软件实现其单元/架构设计规范、证明被…...
高效作业跟踪:SpringBoot作业管理系统
1 绪论 1.1 研究背景 现在大家正处于互联网加的时代,这个时代它就是一个信息内容无比丰富,信息处理与管理变得越加高效的网络化的时代,这个时代让大家的生活不仅变得更加地便利化,也让时间变得更加地宝贵化,因为每天的…...
keepalived + nginx 实现网站高可用性(HA)
keepalive 一、keepalive简介二、实现步骤1. 环境准备2. 安装 Keepalived3. 配置 Keepalived 双机主备集群架构4. 配置 Nginx5. 启动Keepalived6. 测试高可用性7. 配置keepalived 双主热备集群架构 三、虚拟ip 一、keepalive简介 目前互联网主流的实现WEB网站及数据库服务高可用…...
有哪些编辑器,怎样选择编辑器
1. Visual Studio Code (VSCode) 特点: 轻量级且强大:启动速度快,占用资源少,但功能强大。跨平台:支持 Windows、macOS 和 Linux。丰富的扩展生态:拥有庞大的扩展市场,可以安装各种插件来扩展功…...
软件系统开发
目录 软件开发方法 软件开发生命周期 软件开发模型 敏捷方法 敏捷型方法两个特点 敏捷方法的核心思想三点 4个核心价值观 主要敏捷方法 RUP RUP的核心特点: RUP软件开发生命周期 9个核心工作流 RUP裁剪 软件系统工具 软件开发工具 需求分析工具 设计…...
浅谈RPC的实现原理与RPC实战
浅谈RPC的实现原理与RPC实战 什么是RPC?RPC框架基本原理gRPC框架介绍Http/2ProtoBuf gRPC实战一、创建项目二、导入依赖三、编写proto文件编写服务端编写客户端 什么是RPC? RPC(Remote Procedore Call),及远程过程调用,是一种在分布式系统中用于进程间…...
web vue 项目 Docker化部署
Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段: 构建阶段(Build Stage):…...
地震勘探——干扰波识别、井中地震时距曲线特点
目录 干扰波识别反射波地震勘探的干扰波 井中地震时距曲线特点 干扰波识别 有效波:可以用来解决所提出的地质任务的波;干扰波:所有妨碍辨认、追踪有效波的其他波。 地震勘探中,有效波和干扰波是相对的。例如,在反射波…...
【入坑系列】TiDB 强制索引在不同库下不生效问题
文章目录 背景SQL 优化情况线上SQL运行情况分析怀疑1:执行计划绑定问题?尝试:SHOW WARNINGS 查看警告探索 TiDB 的 USE_INDEX 写法Hint 不生效问题排查解决参考背景 项目中使用 TiDB 数据库,并对 SQL 进行优化了,添加了强制索引。 UAT 环境已经生效,但 PROD 环境强制索…...
MVC 数据库
MVC 数据库 引言 在软件开发领域,Model-View-Controller(MVC)是一种流行的软件架构模式,它将应用程序分为三个核心组件:模型(Model)、视图(View)和控制器(Controller)。这种模式有助于提高代码的可维护性和可扩展性。本文将深入探讨MVC架构与数据库之间的关系,以…...
如何为服务器生成TLS证书
TLS(Transport Layer Security)证书是确保网络通信安全的重要手段,它通过加密技术保护传输的数据不被窃听和篡改。在服务器上配置TLS证书,可以使用户通过HTTPS协议安全地访问您的网站。本文将详细介绍如何在服务器上生成一个TLS证…...
【单片机期末】单片机系统设计
主要内容:系统状态机,系统时基,系统需求分析,系统构建,系统状态流图 一、题目要求 二、绘制系统状态流图 题目:根据上述描述绘制系统状态流图,注明状态转移条件及方向。 三、利用定时器产生时…...
从零实现STL哈希容器:unordered_map/unordered_set封装详解
本篇文章是对C学习的STL哈希容器自主实现部分的学习分享 希望也能为你带来些帮助~ 那咱们废话不多说,直接开始吧! 一、源码结构分析 1. SGISTL30实现剖析 // hash_set核心结构 template <class Value, class HashFcn, ...> class hash_set {ty…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个生活电费的缴纳和查询小程序
一、项目初始化与配置 1. 创建项目 ohpm init harmony/utility-payment-app 2. 配置权限 // module.json5 {"requestPermissions": [{"name": "ohos.permission.INTERNET"},{"name": "ohos.permission.GET_NETWORK_INFO"…...
稳定币的深度剖析与展望
一、引言 在当今数字化浪潮席卷全球的时代,加密货币作为一种新兴的金融现象,正以前所未有的速度改变着我们对传统货币和金融体系的认知。然而,加密货币市场的高度波动性却成为了其广泛应用和普及的一大障碍。在这样的背景下,稳定…...
IP如何挑?2025年海外专线IP如何购买?
你花了时间和预算买了IP,结果IP质量不佳,项目效率低下不说,还可能带来莫名的网络问题,是不是太闹心了?尤其是在面对海外专线IP时,到底怎么才能买到适合自己的呢?所以,挑IP绝对是个技…...
