Linux DebugFS 子目录也是用debugfs_create_dir来实现

本文介绍debugFS这一内核调试工具的使用方法,包括如何通过debugFS创建目录、文件及读写内核变量等内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

DebugFS,是一种用于内核调试的虚拟文件系统,内核通过debugfs和用户空间交换数据。类似procfs和sysfs等,这些文件系统都在内存里。

最常用的内核调试手段是printk。但在调试时可能需要修改某些内核变量,这时printk就无能为力,procfs和sysfs虽然也可以实现这个功能,但是偏离了本意,故debugfs从天而降。默认情况下,debugfs会被挂载在目录/sys/kernel/debug之下,如果没有自动挂载,可以用如下命令手动完成:

# mount -t debugfs none /sys/kernel/debug

我们分三种情况说明debugfs如何使用

比如生成树形目录结构如下的调试开关或变量:

mydebug  目录

   subdir   目录

           c       文件

   a           变量

    b          blob变量


其中,a对应模块中的一个u8类型的变量,b和subdir下面的c都是对应模块里的一个字符数组,只是它们的实现方式不同。

在module_init里,我们首先要建立根目录mydebug:

my_debugfs_root = debugfs_create_dir( "mydebug" , NULL);
第一个参数是目录的名称,第二个参数用来指定这个目录的上级目录,如果是NULL,则表示是放在debugfs的根目录里

子目录也是用debugfs_create_dir来实现

sub_dir = debugfs_create_dir("subdir", my_debugfs_root);

建立文件a的代码非常简单:

debugfs_create_u8( "a" , 0644, my_debugfs_root, &a);
这表示文件名为“a”,文件属性是0644,父目录是上面建立的“mydebug”,对应的变量是模块中的a。

b是一个32-bytes的字符数组,在debugfs里,数组可以用blob wrapper来实现。

  char hello[32] = "hello";

  struct debugfs_blob_wrapper b;

  b.data = (void*)hello;

  b.size = strlen(hello) + 1;

  debugfs_create_blob("b", 0444, my_debugfs_root, &b);

  blob wapper定义的数据只能是只读的。

那如何往内核里些数据调试呢?通过自定义的文件操作同时实现了读和写。
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
static int c_open( struct inode *inode, struct file *filp)
{
     filp->private_data = (void*)hello;
     return 0;
}
 
static ssize_t c_read( struct file *filp, char __user *buffer,
         size_t count, loff_t *ppos)
{
     if (*ppos >= 32)
         return 0;
     if (*ppos + count > 32)
         count = 32 - *ppos;
 
     if (copy_to_user(buffer, filp->private + *ppos, count))
         return -EFAULT;
 
     *ppos += count;
 
     return count;
}
 
static ssize_t c_write( struct file *filp, const char __user *buffer,
         size_t count, loff_t *ppos)
{
     if (*ppos >= 32)
         return 0;
     if (*ppos + count > 32)
         count = 32 - *ppos;
 
     if (copy_from_user(filp->private + *ppos, buffer, count))
         return -EFAULT;
 
     *ppos += count;
 
     return count;
}
 
struct file_operations c_fops = {
     .owner = THIS_MODULE,
     .open = c_open,
     .read = c_read,
     .write = c_write,
};
 
 
debugfs_create_file( "c" , 0644, sub_dir, NULL, &c_fops);


三个文件和子目录已经创建完毕。在module_exit中,我们要记得释放创建的数据。

debugfs_remove_recursive可以帮我们逐步移除每个分配的dentry,如果您想一个一个手动的移除,也可以直接调用debugfs_remove。
### 创建 proc 文件条目 `create_proc_entry` 是用于创建 `/proc` 文件系统的文件或目录项的一个函数。此接口允许内核模块向进程文件系统添加自定义入口,从而提供动态数据给用户空间程序访问[^1]。 #### 函数原型 ```c struct proc_dir_entry *create_proc_entry(const char *name, umode_t mode, struct proc_dir_entry *parent); ``` 参数说明如下: - `const char *name`: 新创建的文件名字符串。 - `umode_t mode`: UNIX 权限模式位掩码(读写权限等)。 - `struct proc_dir_entry *parent`: 父级目录节点;如果为 NULL,则默认放置于根路径下。 返回值是一个指向新分配并初始化后的结构体实例指针 (`struct proc_dir_entry`) 或者当操作失败时则返回 NULL。 #### 使用示例 下面展示了一个简单的例子来演示如何利用该 API 实现一个只读属性的小工具,在其中可以查看当前 CPU 频率信息: ```c #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/proc_fs.h> static int read_cpu_freq(char *page, char **start, off_t offset, int count, int *eof, void *data); // 定义 /proc/cpu_frequency 结点 static struct proc_dir_entry *our_proc_file; int init_module(void){ our_proc_file = create_proc_entry("cpu_frequency", 0444, NULL); // 只读方式打开 if (NULL == our_proc_file) { remove_proc_entry("cpu_frequency", &proc_root); printk(KERN_ALERT "Error: Could not initialize /proc/cpu_frequency\n"); return -ENOMEM; } our_proc_file->read_proc = read_cpu_freq; our_proc_file->owner = THIS_MODULE; printk(KERN_INFO "/proc/cpu_frequency created.\n"); return 0; } void cleanup_module(void){ remove_proc_entry("cpu_frequency", NULL); printk(KERN_INFO "/proc/cpu_frequency removed.\n"); } ``` 上述代码片段展示了怎样通过调用 `create_proc_entry()` 方法注册一个新的名为 “cpu_frequency” 的虚拟文件到 `/proc` 下面,并设置好相应的回调处理逻辑以便响应来自应用程序层面对它的查询请求。 需要注意的是现代 Linux 内核版本已经逐渐弃用了这种直接操纵底层对象的方式转而推荐开发者采用更安全高效的替代方案比如 seq_file 接口或是 debugfs 子系统来进行相似功能开发工作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值