debugfs使用指南

debugfs

概述

类似sysfs、procfs,debugfs 也是一种内存文件系统。不过不同于sysfs一个kobject对应一个文件,procfs和进程相关的特性,debugfs的灵活度很大,可以根据

需求对指定的变量进行导出并提供读写接口。debugfs又是一个Linux中 everything is a file 哲学的体现,通过VFS实现了对驱动的控制。可以通过以下命令,来

挂载debugfs到指定目录。

mount -t debugfs none /sys/kernel/debug

支持的读写类型

debugfs支持比较丰富的数据类型,如下所示。

debugfs使用指南

使用方式

1、创建目录和文件

使用 debugfs_create_dir 创建一个目录,如果parent为NULL,则默认其父目录为debugfs的根目录。函数的返回值为NULL表示目录创建成功。

debugfs_create_file和debugfs_create_file_size都用来创建文件,不同的是debugfs_create_file_size可以通过file_size字段指定一个初始的大小。

name:文件名

mode:文件权限可以是整型(比如0644)也可以使用内核的宏

parent:父目录,如果为空则该文件的父目录为根目录

data:inode的i_private字段指向这个结构

fops:表示该文件的自定义操作,需要注意的是在我实际测试中open函数可能是必须要实现的,否则在使用echo命令的时候会报以下的错误

debugfs使用指南
struct dentry *debugfs_create_dir(const char *name, struct dentry *parent);
struct dentry *debugfs_create_file(const char *name, umode_t mode,
                                   struct dentry *parent, void *data,
                                   const struct file_operations *fops);
void debugfs_create_file_size(const char *name, umode_t mode,
                              struct dentry *parent, void *data,
                              const struct file_operations *fops,
                              loff_t file_size);

2、创建无符号整型文件

//创建十进制的无符号文件
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);

3、布尔类型文件

void debugfs_create_bool(const char *name, umode_t mode,
                         struct dentry *parent, bool *value);

读布尔文件会显示Y或者N,写该文件时,只接受(Y, N, y, n, 0, 1)等值,其他值都只会被简单的忽略。

4、原子类型

void debugfs_create_atomic_t(const char *name, umode_t mode,
                             struct dentry *parent, atomic_t *value)

5、blob类型

使用debugfs_create_blob创建一个blob类型的文件,调用该函数前,我们需要在debugfs_blob_wrapper的data字段指定要展示的内容,size表示data长度。

需要注意的是blob类型的文件是只读的

struct debugfs_blob_wrapper {
    void *data;
    unsigned long size;
};

struct dentry *debugfs_create_blob(const char *name, umode_t mode,
                                   struct dentry *parent,
                                   struct debugfs_blob_wrapper *blob);

6、寄存器类型

使用 debugfs_reg32 表示一个寄存器内容,name表示文件名,offset表示相对于基地址的偏移。debugfs_regset32 表示一组寄存器文件,nregs:寄存器文件个数 base:io基地址

struct debugfs_reg32 {
    char *name;
    unsigned long offset;
};

struct debugfs_regset32 {
    const struct debugfs_reg32 *regs;
    int nregs;
    void __iomem *base;
    struct device *dev;     /* Optional device for Runtime PM */
};

debugfs_create_regset32(const char *name, umode_t mode,
                        struct dentry *parent,
                        struct debugfs_regset32 *regset);

void debugfs_print_regs32(struct seq_file *s, const struct debugfs_reg32 *regs,
                     int nregs, void __iomem *base, char *prefix);

踩坑

1、debugfs的API的都是GPL的,因此在自己的模块必须要指定协议为GPL

2、使用echo写文件的话,open函数是必须的。

代码实例

#include
#include
#include
#include
#include
#include
#include

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

Original: https://www.cnblogs.com/dennis-wong/p/16391598.html
Author: 成蹊0xc000
Title: debugfs使用指南

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/582758/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 四大高阶函数、匿名函数、递归

    四大高阶函数: map、reduce、filter、sorted 1.map函数: 根据提供的函数对指定序列做映射 使用可迭代对象(指定的序列)中的每个元素调用函数,将返回值作为新…

    Linux 2023年6月8日
    0108
  • Golang 实现 Redis(4): AOF 持久化与AOF重写

    AOF 持久化是典型的异步任务,主协程(goroutine) 可以使用 channel 将数据发送到异步协程由异步协程执行持久化操作。 在 DB 中定义相关字段: type DB …

    Linux 2023年5月28日
    099
  • 异常—异常安全问题–内存泄漏动图演示

    异常是一种处理错误的方式,当一个函数发现自己无法处理的错误时就可以抛出异常,让函数的 直接或间接的调用者处理这个错误。 throw: 当问题出现时,程序会抛出一个异常。这是通过使用…

    Linux 2023年6月13日
    087
  • SpringBoot学习笔记——Redis Template

    Springboot可以通过redis template和redis进行交互,使用方法如下 可以参考这个系列的文章: 【快学springboot】11.整合redis实现sessi…

    Linux 2023年5月28日
    099
  • 001.云桌面整体解决方案实施

    桌面云概述 桌面云介绍 本桌面云整体交付方案基于深信服aDesk桌面云实现。 深信服桌面云是采用云计算的思想,将用户的桌面操作系统以服务的形式通过网络进行交付,可以让用户在不同设备…

    Linux 2023年6月13日
    0111
  • 从Windows备份文件到Linux服务器

    各种深坑 尝试1—FTP 因为组内有FTP服务器,所以尝试用bat编写把文件压缩后放到FTP上。其中压缩使用7zip.exe来完成,定时任务使用windows自带的定时任务。 整个…

    Linux 2023年6月8日
    0112
  • 投票活动进行中!探讨问题:从互联网大量收集学习资料再包装成产品售卖盈利是否属于侵权违法?

    写在开篇 今天不聊某项技能的知识点,我们聊点别的。那么,到底聊啥好呢?笔者想想… 有了,这两天笔者从一个微信公众号中发现一个非常恶劣的营销行为。事情大概背景是这样的:运…

    Linux 2023年6月7日
    077
  • 教你搞懂Jenkins安装部署!

    前言:请各大网友尊重本人原创知识分享,谨记本人博客: 南国以南i Jenkins介绍 Jenkins是一个开源软件项目,是基于Java开发的一种持续集成工具,用于监控持续重复的工作…

    Linux 2023年6月14日
    0123
  • nginx配置只允许域名访问,禁止ip访问80,443端口

    一、背景客户扫描阿里云服务器,发现渗透漏洞(.git文件泄露漏洞),可以直接使用IP访问项目底下的某个文件,针对这个问题,需要对nginx进行配置,不使用IP访问项目,而只能使用域…

    Linux 2023年6月14日
    086
  • MacOS设置终端代理

    前言 国内的开发者或多或少都会因为网络而烦恼,因为一些特殊原因有时候网络不好的时候需要使用代理才能完成对应的操作。原来我一直都是使用斐讯路由器然后刷了梅林的固件,直接在路由器层面设…

    Linux 2023年6月14日
    092
  • 从前端走向后端

    每次过年回老家聚会,遇到不熟悉的亲戚朋友,经常被问到职业是什么。一开始,我总是很认真的回答这个问题,结果常常引出一番尴尬的问答。 “你&…

    Linux 2023年6月6日
    097
  • AI场景存储优化:云知声超算平台基于 JuiceFS 的存储实践

    云知声是一家专注于语音及语言处理的技术公司。 Atlas 超级计算平台是云知声的计算底层基础架构,为云知声在 AI 各个领域(如语音、自然语言处理、视觉等)的模型迭代提供训练加速等…

    Linux 2023年6月14日
    092
  • 20 年老程序员告诉你的 20 条编码原则

    我从 1999 年就开始了编程生涯,到今年已经有 20 多年了。我先是从 Basic 开始,很快转到了 Pascal 和 C 语言,然后又学习了面向对象编程语言 Delphi 和 …

    Linux 2023年6月8日
    097
  • redis启动失败 提示Unregistered Authentication Agent for unix-process:6176

    使用宝塔软件安装的redis 一直没启动起来。 使用 journalctl -xe 命令查看原因,发现redis.pid已经存在。 进入该目录,删除redis.pid。 再使用sy…

    Linux 2023年5月28日
    0334
  • OpenStack cinder对接glusterfs存储

    一、创建虚拟机node1 自定义默认下一步稍后安装操作系统选择Linux,红帽6名称位置随意1核就行2G内存就行仅主机网络默认下一步默认下一步默认下一步30G,给单个文件添加一块5…

    Linux 2023年6月8日
    089
  • UE4在Windows下交叉编译打包Linux版本

    UE4在Windows下交叉编译打包Linux版本 我使用的是UE4.27.2,Windows 11,项目是一个 纯蓝图项目,所以打包过程没有什么阻碍。 首先上官网下载对应版本的工…

    Linux 2023年6月6日
    099
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球