首页 > 系统相关 >Linux内核debugfs介绍

Linux内核debugfs介绍

时间:2023-05-15 16:04:22浏览次数:47  
标签:const name dentry debugfs create 内核 Linux struct

前言

内核开发者经常需要导出一些信息到用户空间,用于分析内核运行逻辑。最常见的方法是使用 printk(),不过在嵌入式中,printk() 往往直接打印到 console,一旦 printk() 被频繁调用的话,console 就会被刷屏,此时输入命令都是件困难的事情。

有时我们只想偶尔看一下某个内核变量的值,但是一旦使用 printk(),它就会无休止地循环打印;另一方面,使用 printk() 只能打印,而不能从用户空间去修改内核变量的值。为了应对这种情况,我们可以使用 procfs 和 sysfs 这两个虚拟文件系统来实现上述需求。不过通过 procfs 和 sysfs 创建一个文件,来读写某个变量的值,从编码角度看,略微复杂了些。

Debugs

Debugfs 作为内核开发人员向用户空间提供信息的一种简单方法而存在。与/proc 不同,它只用于处理有关进程的信息,而 sysfs 有严格的每个文件一个值的规则,debug fs 根本没有规则。开发人员可以将他们想要的任何信息放在那里。Debug 文件系统还不能作为用户空间的稳定 ABI; 理论上,导出的文件没有稳定性约束。现实世界并不总是那么简单,尽管如此; 即使是调试接口的最佳设计思想也是需要永久维护的。

调试通常使用以下命令安装,或等效的/etc/fstab写入要挂载的文件系统:
mount -t debugfs none /sys/kernel/debug

默认情况下,只有root用户才能访问 debugfs 根目录。要更改对树的访问,可以使用“ uid”、“ gid”和“ mode”挂载选项。

使用debugfs的内核模块

很多低功耗相关的模块都使用了debugfs

  • clk
  • regulator
  • pinctrl
  • gpio
  • devfreq
  • pm
  • etc

debugfs的使用

创建目录

使用debugfs的代码应该包括<linux/debugfs.h>。然后,第一步是创建至少一个目录来保存一组debugfs文件。

如果调用成功,将在指定的父目录下创建一个名为name的目录。如果父目录为NULL,则将在debugfs根目录中创建该目录。成功后,返回值是一个struct-dentry指针,可用于在目录中创建文件(并在最后清理)。ERR_PTR(-ERROR)返回值表示失败。如果返回ERR_PTR(-ENODEV),则表明内核是在没有debugfs支持的情况下构建的,并且下面描述的函数都无法工作。

struct dentry *debugfs_create_dir(const char *name, struct dentry *parent);

创建文件节点

这里,name是要创建的文件的名称,mode描述文件应该具有的访问权限,parent表示应该保存文件的目录,数据将存储在生成的inode结构的i_private字段中,fops是一组实现文件行为的文件操作。至少应该提供read()和/或write()操作;可以根据需要包括其他的。同样,返回值将是指向创建文件的dentry指针,错误时为ERR_PTR(-ERROR),如果缺少debugfs支持,则为ERR_PTR(-ENODEV)。在debugfs目录中创建文件的最常见方法是:

struct dentry *debugfs_create_file(const char *name, umode_t mode,
                                   struct dentry *parent, void *data,
                                   const struct file_operations *fops);

创建整数值文件

在许多情况下,实际上并不需要创建一组文件操作;debugfs代码为简单的情况提供了许多辅助函数。这些文件支持读取和写入给定的值; 如果不应该写入特定的文件,只需相应地设置模式位。有十进制的接口,也有十六进制的接口

十进制

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
  • long
  • xul
  • bool
void debugfs_create_size_t(const char *name, umode_t mode,
                           struct dentry *parent, size_t *value);

struct dentry *debugfs_create_ulong(const char *name, umode_t mode,
                                    struct dentry *parent,
                                    unsigned long *value);
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);

导出二进制块

读取此文件将返回debugfs_blob_wrapper结构所指向的数据。一些驱动程序使用“blobs”作为返回几行(静态)格式化文本输出的简单方法。这个函数可以用来导出二进制信息,但在主线中似乎没有任何代码可以这样做。请注意,使用debugfs_create_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);

导出数组

“array”参数包装一个指向数组数据及其元素数的指针。注意:一旦创建了数组,其大小就无法更改。

struct debugfs_u32_array {
    u32 *array;
    u32 n_elements;
};

void debugfs_create_u32_array(const char *name, umode_t mode,
                    struct dentry *parent,
                    struct debugfs_u32_array *array);

文件相关

命名

对 debug fs _ rename()的调用将为现有的 debug 文件提供一个新名称,可能位于不同的目录中。New _ name 在调用之前不能存在; 返回值为 old _ dentry,其中包含更新的信息。可以使用 degugfs _ create _ symlink ()创建符号链接。

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

删除

所有debugfs用户都必须考虑一件重要的事情:在debugfs中创建的任何目录都不会自动清理。如果卸载模块时没有明确删除debugfs条目,那么结果将是大量过时的指针,并且会出现高度反社会的行为。因此,所有的debugfs用户——至少是那些可以作为模块构建的用户——都必须准备好删除他们在那里创建的所有文件和目录。可以使用以下方法删除文件:
void debugfs_remove(struct dentry *dentry);
debugfs用户需要记住他们创建的每个debugfs文件的dentry指针,以便可以清理所有文件。不过,我们现在生活在一个更加文明的时代,debugfs用户可以调用:如果向该函数传递与顶级目录对应的dentry的指针,则该目录下的整个层次结构将被删除。
void debugfs_remove_recursive(struct dentry *dentry);

Ref

https://docs.kernel.org/filesystems/debugfs.html

标签:const,name,dentry,debugfs,create,内核,Linux,struct
From: https://www.cnblogs.com/lvzh/p/17402134.html

相关文章

  • 将java开发环境装入linux系统
    使用该指令下载jdkwgethttps://dragonwell.oss-cn-shanghai.aliyuncs.com/8.6.6/Alibaba_Dragonwell_8.6.6_x64_linux.tar.gz使用 tarxf+文件名 解压文件tarxfAlibaba_Dragonwell_8.6.6_x64_linux.tar.gz配置环境变量vim/etc/profile 打开环境变量文件exportJAV......
  • linux标准输入/输出/错误及重定向
    标准输入/输出/错误linux下每个进程在运行的过程中都会打开一系列的文件,可以通过lsof-p$pid来查看进程号为pid打开的文件,在/proc/pid/fd/下是该进程打开的文件的链接。其中有三个比较特殊的文件是每个进程都会打开,其文件描述符分为0,1,2,默认分别链接到标准输入(STDIN_FILENO)设备......
  • linux常用命令
    crul"访问地址"模拟访问地址ps-ef|grepelastices的运行状态./elasticsearch-des启动命令exit退出当前用户chown-Relastic:elastic*增加目录权限和冒号后面迭代所有的目录rm-rf文件删除文件cp拷贝的文件拷贝文件的目录和文件名./shutdown.sh关闭tomcat./......
  • linux 命令行出现-bash-4.2$的解决办法
    linux命令行出现-bash-4.2$的解决办法reference:https://blog.csdn.net/weixin_40106836/article/details/86495232https://blog.csdn.net/mjb115889/article/details/82115708现象:命令行出现-bash-4.2$,而非默认的[用户名@主机名:]的格式。处理方法:输入这两句话,然后关闭终端......
  • Linux下基于iptables的hashlimit模块限速
    记录一下:【对目标IP限制下载速率】出站包,目标IP为x.x.x.x,限速200KBytes/s:iptables-AOUTPUT-dx.x.x.x-mhashlimit--hashlimit-above200kb/s--hashlimit-modedstip--hashlimit-nameout-jDROP 【对自身tcp/12345提供的服务限制下载速率】出站包,源端口是tcp/12......
  • Linux Centos7系统 设置java jar包开机自启
    #/bin/bashsource/etc/profile#刷新环境变量#定义服务路径webServerPath=/data/web#启动自定义服务(两个)nohupjava-jar$webServerPath/rbpsems-web-2.0.0-SNAPSHOT-boot.jar>$webServerPath/nohup.out2>&1&nohupjava-jar/data/lv/forward-lvfu-0.0.1-SNAPSHOT.jar......
  • 《Linux操作系统分析》课程总结报告
    《Linux操作系统分析》课程总结报告一、Linux系统的一般执行过程最一般的情况:正在运行的用户态进程X切换到运行用户态进程Y的过程正在运行的用户态进程X发生中断savecs:eip/esp/eflags(current)tokernelstackloadcs:eip(entryofaspecificISR)andss:esp(point......
  • Linux的一些命令记录
    tar压缩tar-cvfxxx.tarxxx#-c打包,仅打包,无压缩tar-zcvfxxx.tar.gz-Cxxx#-z表示用gzip压缩,常以gz或tgz结尾,-C打包xxx目录的所有内容解压tar-zxvfxxx.tar.gz#-x表示解压选项-c压缩;-x解压;-z使用gzip;-v显示所有过程;-f使用档案名字解决csdn无法复制的问......
  • Linux文件查找命令之locate与find
    locate与find是经常使用的Linux 命令,刚接触Linux时对这两个命令的使用傻傻的分不清。现在我们来对比一下两个命令到底有哪些区别。locatelocate让使用者可以很快速的搜寻档案系统内是否有指定的档案。其方法是先建立一个包括系统内所有档案名称及路径的数据库,之后当寻找......
  • RedHat Enterprise Linux 8.0终端命令界面字体放大缩小
    一、打开RedHat的终端命令界面。 二、放大界面中字体,Ctrl+Shit +“+”三、缩小界面中字体,Ctrl+ “-” ......