Linux下的Debugfs

debugfs


1. 简介

类似sysfs、procfsdebugfs 也是一种内存文件系统。不过不同于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介绍

debugfs_create_dir

struct dentry *debugfs_create_dir(const char *name, struct dentry *parent);
参数作用备注
name文件夹名称
parent父目录如果为NULL,则在root根目录下

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 : 读操作
// set : 写操作
// fmt : 用于指定 get 和 set 函数的输入输出格式。
//例如,它可以定义一个整数、浮点数或字符串的格式,以便在 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);	\
}									\
static const struct file_operations __fops = {				\
	.owner	 = THIS_MODULE,						\
	.open	 = __fops ## _open,					\
	.release = simple_attr_release,					\
	.read	 = simple_attr_read,					\
	.write	 = simple_attr_write,					\
	.llseek	 = generic_file_llseek,					\
}

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");

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【论文速读】Optimization-based Prompt Injection Attack to LLM-as-a-Judge

基于优化的提示词注入攻击 摘要引言问题描述LLM-as-a-judge威胁模型攻击者知道什么 JUDGEDECEIVER 细节概述生成影子候选回复公式化为优化问题Target-aligned generation lossTarget-enhancement lossAdversarial perplexity loss优化问题 求解优化问题 摘要 LLM-as-a-Judge 利…

单智能体carla强化学习实战工程介绍

有三个工程&#xff1a; Ray_Carla: 因为有的论文用多进程训练强化学习&#xff0c;包括ray分布式框架等&#xff0c;这里直接放了一个ray框架的示例代码&#xff0c;是用sac搭建的&#xff0c;obs没用图像&#xff0c;是数值状态向量值&#xff08;速度那些&#xff09;。 …

PD取电快充协议芯片,XSP08Q在灯具中的应用

前言 随着快充技术不断的发展 USB Type-C端口的普及 PD快充成了电子设备中的宠儿&#xff0c;在各种电子设备领域都能见到PD快充的身影&#xff0c;不得不说快充技术的出现让电子设备在充电的速度上得到前所未有的体验&#xff0c;大大的缩短了设备的充电时间。快充协议芯片不…

【AI开源项目】Botpress - 开源智能聊天机器人平台及其部署方案

文章目录 Botpress 概述Botpress 的定位 Botpress 的主要特点1. OpenAI 集成2. 易于使用3. 定制和扩展性4. 多平台支持5. 集成和扩展 API6. 活跃的社区和详尽的文档 部署方案集成集成开发集成部署机器人示例开发工具代理本地开发先决条件从源代码构建 Botpress 如何解决常见问题…

【天线&运输】交通事故严重程度检测系统源码&数据集全套:改进yolo11-HSFPN

改进yolo11-ASF-DySample等200全套创新点大全&#xff1a;交通事故严重程度检测系统源码&#xff06;数据集全套 1.图片效果展示 项目来源 人工智能促进会 2024.11.01 注意&#xff1a;由于项目一直在更新迭代&#xff0c;上面“1.图片效果展示”和“2.视频效果展示”展示的系…

使用 Elastic、OpenLLMetry 和 OpenTelemetry 跟踪 LangChain 应用程序

作者&#xff1a;来自 Elastic Bahubali Shetti Langchain 应用程序的使用正在增长。构建基于 RAG 的应用程序、简单的 AI 助手等的能力正在成为常态。观察这些应用程序更加困难。考虑到现有的各种选项&#xff0c;本博客展示了如何将 OpenTelemetry 检测与 OpenLLMetry 结合使…

揭秘Scam-as-a-Service:警惕钓鱼攻击的产业化

2024年6月开始&#xff0c;CertiK安全团队监控到大量相似的phishing/drainer transaction&#xff0c;仅6月份监控到的涉案金额就超过5500万美元&#xff0c;进入8、9月份后&#xff0c;相关钓鱼地址的活动更加频繁&#xff0c;钓鱼攻击有愈演愈烈的架势。整个2024年第三季度&a…

前端Election

一.什么是Election 1.一款应用广泛的跨平台和桌面应用开发框架。 2.本质 Election的本质是结合了Chromium与Node.js 3.构建 使用HTML ,CSS,JS等Web技术构建桌面应用程序。 只要最后能转换成html css js即可 二.流程模型 1.主进程 关于node.js的任何api都在这里调用 一个纯…

如何在Linux系统中使用SSH进行安全连接

如何在Linux系统中使用SSH进行安全连接 SSH简介 安装SSH 在Debian/Ubuntu系统中安装 在CentOS/RHEL系统中安装 启动SSH服务 验证SSH是否安装成功 SSH配置 配置监听端口 配置登录方式 SSH客户端 安装SSH客户端 使用SSH客户端 SSH密钥认证 生成SSH密钥对 复制公钥到远程服务器…

SpringBoot源码解析(一)

SpringBoot自动装配原理 SpringBootApplication注解 我们在使用SpringBoot时&#xff0c;通常使用的是SpringBootApplication这个注解&#xff0c;比如&#xff1a; 而这个注解的定义为下图&#xff0c;可以发现这个注解上有另外三个注解&#xff1a;SpringBootConfiguration…

BES2600WM---HiLink RM56 EVK

0 Preface/Foreword 0.1 路径 OpenHarmony/device_soc_bestechnic - 码云 - 开源中国 https://github.com/Hi-LinkDuino/RM56 1 环境搭建 1.1 安装依赖工具 sudo apt-get install build-essential gcc g make zlib* libffi-dev e2fsprogs pkg-config flex bison perl bc ope…

C# 编程语言学习教程

C# 编程语言学习教程 目录 C# 简介 1.1 什么是 C#1.2 C# 的特点1.3 C# 的应用领域 环境搭建 2.1 安装 Visual Studio2.2 创建第一个 C# 项目 基础语法 3.1 数据类型3.2 控制结构3.3 数组与字符串 面向对象编程 4.1 类与对象4.2 继承与多态4.3 接口与抽象类 常用库与框架 5.1 .…

PAT甲级-1092 To Buy or Not to Buy

题目 题目大意 Eva想要买珠子&#xff0c;但是只能按串买。如果串上有她想要买的所有珠子&#xff0c;那么输出“Yes”&#xff0c;再输出需要额外买几个珠子。如果串上缺少她想要的珠子&#xff0c;那么输出“No”&#xff0c;并输出缺少的珠子个数。其中&#xff0c;s1是商店…

使用WebAssembly优化Web应用性能

&#x1f493; 博客主页&#xff1a;瑕疵的CSDN主页 &#x1f4dd; Gitee主页&#xff1a;瑕疵的gitee主页 ⏩ 文章专栏&#xff1a;《热点资讯》 使用WebAssembly优化Web应用性能 引言 WebAssembly 简介 编译 WebAssembly 模块 使用 Emscripten 编译 C/C 代码 使用 Rust 编译…

【C语言】自定义类型(结构体、枚举、联合的详解)下

写在前面 书接上回&#xff1a;【C语言】自定义类型&#xff08;结构体、枚举、联合的详解&#xff09;上 在上中&#xff0c;不才独篇撰写了结构体的具体细节&#xff0c;本篇笔记主要是把剩下的自定义类型全部展示。 文章目录 写在前面二、位段2.1、位段的定义2.2、位段占用…

初始JavaEE篇 —— 文件操作与IO

找往期文章包括但不限于本期文章中不懂的知识点&#xff1a; 个人主页&#xff1a;我要学编程程(ಥ_ಥ)-CSDN博客 所属专栏&#xff1a;JavaEE 目录 文件介绍 Java标准库中提供操作文件的类 文件系统操作 File类的介绍 File类的使用 文件内容操作 二进制文件的读写操作…

CSP 2024 入门级第二轮 CSP-J 2024 复赛 第一题 扑克牌

一、题目阅读 [CSP-J 2024] 扑克牌 - 洛谷 二、题目解析 输入 去重 三、题目代码 #include <bits/stdc.h> using namespace std;int main() {map<string, bool> flag;int n, res 52;cin >> n;while (n--) {string s;cin >> s;if (!flag[s]) { // …

面试题:JVM(二)

1. 面试题 简述 Java 类加载机制?&#xff08;百度&#xff09; JVM类加载机制 &#xff08;滴滴&#xff09; JVM中类加载机制&#xff0c;类加载过程&#xff0c;什么是双亲委派模型&#xff1f; &#xff08;腾讯&#xff09; JVM的类加载机制是什么&#xff1f; &#x…

AUTOSAR CP MCAL微控制器抽象层介绍

AUTOSAR(Automotive Open System Architecture)即汽车开放系统架构,它将汽车电子控制单元(ECU)的软件底层做了一个标准的封装,使得开发者能够共用一套底层软件,并通过修改参数来匹配不同的硬件和应用层软件。AUTOSAR CP(Classic Platform)是AUTOSAR架构中的一个重要组…

ElastricSearch 原理以及简单实用(超级通俗)

提到非结构化数据的检索&#xff0c;常常用到 ElasticSearch&#xff0c;他是什么呢&#xff1f; ElasticSearch 是一个基于 Apache Lucene 的分布式搜索引擎&#xff0c;可以作为实时文档存储系统&#xff0c;且文档的每一个内容都可以被检索&#xff0c;能够处理 PB 级别的结…