debugfs 使用指南

debugfs 使用指南  https://zhuanlan.zhihu.com/p/651692040

Linux驱动调试中的Debugfs的使用简介 CONFIG_DEBUG_FS 的功能与配置  https://blog.csdn.net/u013165704/article/details/80777799

linux DebugFS介绍  https://zhuanlan.zhihu.com/p/487700961


debugfs使用指南

https://www.cnblogs.com/dennis-wong/p/16391598.html

ebugfs#

概述#

类似sysfs、procfs,debugfs 也是一种内存文件系统。不过不同于sysfs一个kobject对应一个文件,procfs和进程相关的特性,

debugfs的灵活度很大,可以根据需求对指定的变量进行导出并提供读写接口。

debugfs又是一个Linux中 everything is a file 哲学的体现,通过VFS实现了对驱动的控制。可以通过以下命令,来挂载debugfs到指定目录。

mount -t debugfs none /sys/kernel/debug

支持的读写类型#

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命令的时候会报以下的错误

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);
  1. 创建无符号整型文件
//创建十进制的无符号文件
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);
  1. 布尔类型文件
void debugfs_create_bool(const char *name, umode_t mode,
                         struct dentry *parent, bool *value);

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

  1. 原子类型
void debugfs_create_atomic_t(const char *name, umode_t mode,
                             struct dentry *parent, atomic_t *value)
  1. 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);    
  1. 寄存器类型

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

修订记录#

202306123 修改了文章格式

作者:dennis-wong

出处:https://www.cnblogs.com/dennis-wong/p/16391598.html

版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
`debugfs` 是一个用于调试文件系统的工具,可以用来查看和修改文件系统的元数据,包括 inode、块、目录等信息。它通常用于恢复损坏的文件系统或者进行文件系统的调试和分析。 以下是 `debugfs` 常用的一些命令和用法: 1. 打开文件系统 ``` debugfs /dev/device ``` 这个命令会打开 `/dev/device` 设备对应的文件系统,以便进行调试操作。请注意,使用 `debugfs` 命令需要以 root 用户身份运行。 2. 查看 inode 节点 ``` debugfs: inode <inode> ``` 这个命令会查看指定 inode 节点的详细信息,包括文件类型、权限、大小、数据块列表等。 3. 查看目录内容 ``` debugfs: ls <directory> ``` 这个命令会列出指定目录下的所有文件和子目录。 4. 查看数据块内容 ``` debugfs: dump <block> ``` 这个命令会查看指定数据块的内容。请注意,这里的数据块编号是逻辑块编号,不是物理块编号。 5. 查找文件名对应的 inode 节点 ``` debugfs: ncheck <inode> ``` 这个命令会查找指定 inode 节点对应的文件名和路径。 6. 查找数据块对应的文件名和 inode 节点 ``` debugfs: icheck <block> ``` 这个命令会查找指定数据块所属的文件名和 inode 节点。 7. 修改 inode 节点的属性 ``` debugfs: set_inode_field <inode> <field> <value> ``` 这个命令会修改指定 inode 节点的属性。其中,`<field>` 可以是 `mode`、`uid`、`gid`、`atime`、`ctime`、`mtime`、`size` 等字段。 8. 修改数据块的内容 ``` debugfs: write <block> <file> ``` 这个命令会将指定文件的内容写入指定数据块中。 请注意,使用 `debugfs` 命令需要非常小心,因为不正确的操作可能会损坏文件系统。建议在进行任何修改之前先备份文件系统。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值