前言
内核开发者经常需要导出一些信息到用户空间,用于分析内核运行逻辑。最常见的方法是使用 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