procfs、debugfs

本文介绍了Procfs和Debugfs这两个伪文件系统的作用与实现方式。Procfs用于获取内核和进程信息,而Debugfs则主要用于调试目的。文章详细解释了它们如何帮助用户和应用程序动态地读取和修改系统信息及内核参数。

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

procfs 是进程文件系统(file system) 的缩写,包含一个伪文件系统,用于通过内核访问进程信息
这个文件系统通常被挂载到 /proc 目录。由于 /proc 不是一个真正的文件系统,它也就不占用存储空间,只是占用有限的内存

伪文件系统
用户和应用程序可以通过proc得到系统的信息,并可以改变内核的某些参数。proc文件系统是动态从系统内核读出所需信息并提交的

优点
在调试时修改某些内核变量,而printk无能为力;为了修改某个值重新编译内核或者驱动过于低效

安装文件系统

# mount -t debugfs none /mnt

头文件

linux/debugfs.h

创建目录

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

创建文件

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

name就是创建的名字;parent是父目录;mode是这个文件读写权限;data是传入的参数;fops为实现在该文件上进行文件操作的fiel_operations结构指针

变量处理

struct dentry *debugfs_create_u8(const char *name, mode_t mode, struct dentry *parent, u8 *value);
struct dentry *debugfs_create_u16(const char *name, mode_t mode, struct dentry *parent, u16 *value);
struct dentry *debugfs_create_u32(const char *name, mode_t mode, struct dentry *parent, u32 *value);
struct dentry *debugfs_create_u64(const char *name, mode_t mode, struct dentry *parent, u64 *value);
struct dentry *debugfs_create_bool(const char *name, mode_t mode, struct dentry *parent, u32 *value);
struct dentry *debugfs_create_blob(const char *name, mode_t mode, struct dentry *parent, struct debugfs_blob_wrapper *blob);

删除文件

void debugfs_remove(struct dentry *dentry);
void debugfs_remove_recursive(struct dentry *dentry);

举例
debugfs

my_debugfs_root = debugfs_create_dir("mydebug", NULL); //根目录
sub_dir = debugfs_create_dir("subdir", my_debugfs_root); //子目录
debugfs_create_u8("a", 0644, my_debugfs_root, &a);

char hello[32] = "Hello world!\n";
struct debugfs_blob_wrapper b;

b.data = (void *)hello;
b.size = strlen(hello) + 1;
debugfs_create_blob("b", 0644, my_debugfs_root, &b);

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);
<think>我们首先需要理解debugfs的作用:它是Linux内核提供的一个用于调试的虚拟文件系统,允许内核开发者向用户空间导出调试信息或允许用户空间向内核传递参数。使用debugfs可以避免频繁使用printk,并且可以动态地读取或修改内核中的某些变量。 接下来,我们将编写一个简单的字符设备驱动示例,该驱动将使用debugfs接口。我们将实现以下功能: 1. 创建一个debugfs目录。 2. 在该目录下创建几个debugfs文件,分别用于读取和写入驱动中的一些变量。 假设我们的驱动中有一个整型变量`debug_value`,我们将创建两个文件: - `value`:用于读取和写入`debug_value`。 - `status`:只读文件,用于显示设备的状态信息。 此外,我们还会创建一个子目录,并在子目录中创建一个文件。 步骤: 1. 包含必要的头文件。 2. 定义驱动所需的全局变量和结构。 3. 实现debugfs文件的读/写回调函数。 4. 在驱动初始化时创建debugfs目录和文件。 5. 在驱动退出时移除debugfs目录和文件。 注意:debugfs的API可能会随着内核版本变化而变化,我们这里使用较新的API(如使用`debugfs_create_*`系列函数)。 示例代码基于Linux内核4.x以上版本。 下面是一个完整的内核模块示例代码:</think>### Linux内核驱动中debugfs接口的实现与使用 debugfs是Linux内核提供的用于调试的虚拟文件系统,允许内核开发者向用户空间导出调试信息。以下是一个完整的驱动示例,展示如何创建debugfs接口: ```c #include <linux/module.h> #include <linux/kernel.h> #include <linux/debugfs.h> #include <linux/fs.h> #include <linux/uaccess.h> #define DRIVER_NAME "debugfs_demo" #define DEBUGFS_DIR "demo_debugfs" static struct dentry *debugfs_dir; static u32 debug_value = 100; static char debug_buffer[128] = "Hello DebugFS!\n"; // 读取回调函数 static ssize_t debug_value_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { char buf[32]; int len = snprintf(buf, sizeof(buf), "%u\n", debug_value); return simple_read_from_buffer(user_buf, count, ppos, buf, len); } // 写入回调函数 static ssize_t debug_value_write(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos) { char buf[32]; unsigned long val; if (count >= sizeof(buf)) return -EINVAL; if (copy_from_user(buf, user_buf, count)) return -EFAULT; buf[count] = '\0'; if (kstrtoul(buf, 0, &val)) return -EINVAL; debug_value = val; return count; } // 只读文件操作 static ssize_t debug_status_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { return simple_read_from_buffer(user_buf, count, ppos, debug_buffer, strlen(debug_buffer)); } // 文件操作结构体 static const struct file_operations debug_value_fops = { .read = debug_value_read, .write = debug_value_write, .owner = THIS_MODULE, }; static const struct file_operations debug_status_fops = { .read = debug_status_read, .owner = THIS_MODULE, }; static int __init debugfs_demo_init(void) { // 创建debugfs目录 debugfs_dir = debugfs_create_dir(DEBUGFS_DIR, NULL); if (!debugfs_dir) { pr_err("Failed to create debugfs directory\n"); return -ENOMEM; } // 创建可读写文件 debugfs_create_file("value", 0644, debugfs_dir, NULL, &debug_value_fops); // 创建只读文件 debugfs_create_file("status", 0444, debugfs_dir, NULL, &debug_status_fops); // 创建单值文件 debugfs_create_u32("u32_value", 0644, debugfs_dir, &debug_value); pr_info("%s initialized\n", DRIVER_NAME); return 0; } static void __exit debugfs_demo_exit(void) { // 递归删除整个目录 debugfs_remove_recursive(debugfs_dir); pr_info("%s removed\n", DRIVER_NAME); } module_init(debugfs_demo_init); module_exit(debugfs_demo_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Your Name"); MODULE_DESCRIPTION("DebugFS Interface Demo"); ``` #### 实现说明: 1. **目录创建**:使用`debugfs_create_dir()`创建根目录`/sys/kernel/debug/demo_debugfs` 2. **文件创建**: - `debugfs_create_file()`:创建自定义读写文件 - `debugfs_create_u32()`:创建自动处理32位整数的文件 3. **文件操作**: - `value`:可读写文件,通过`debug_value_read/write`函数操作 - `status`:只读文件,显示固定内容 - `u32_value`:自动生成的整型文件 4. **内存安全**: - 使用`copy_from_user()`确保用户空间数据安全复制 - 使用`simple_read_from_buffer()`简化读取操作 #### 使用示例: ```bash # 查看文件 ls /sys/kernel/debug/demo_debugfs # value status u32_value # 读取值 cat /sys/kernel/debug/demo_debugfs/value # 100 # 写入新值 echo 200 > /sys/kernel/debug/demo_debugfs/value # 查看自动更新值 cat /sys/kernel/debug/demo_debugfs/u32_value # 200 # 查看状态 cat /sys/kernel/debug/demo_debugfs/status # Hello DebugFS! ``` #### 注意事项: 1. debugfs仅用于调试,生产环境应禁用 2. 文件权限需合理设置(如0444表示只读) 3. 必须实现`debugfs_remove_recursive()`清理资源 4. 用户空间交互需严格验证输入数据 5. 适用于内核4.x及以上版本[^1] debugfs相比procfs和sysfs更适合调试场景,因为它不限制数据类型和格式,可以直接操作内核数据结构[^1][^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值