debugfs是Linux内核提供的一个用于调试的虚拟文件系统,它允许驱动开发人员在内核空间和用户空间之间快速交换调试信息。下面我将详细介绍如何在Linux驱动中创建和使用debugfs接口。
/sys/kernel/debug/
目录下#include <linux/debugfs.h>
struct dentry *debugfs_create_dir(const char *name, struct dentry *parent);
void debugfs_remove(struct dentry *dentry);
// 创建普通文件
struct dentry *debugfs_create_file(const char *name, umode_t mode,
struct dentry *parent, void *data,
const struct file_operations *fops);
// 创建布尔文件
struct dentry *debugfs_create_bool(const char *name, umode_t mode,
struct dentry *parent, u32 *value);
// 创建X32文件(32位无符号整型)
struct dentry *debugfs_create_x32(const char *name, umode_t mode,
struct dentry *parent, u32 *value);
// 创建原子变量文件
struct dentry *debugfs_create_atomic_t(const char *name, umode_t mode,
struct dentry *parent,
atomic_t *value);
// 创建blob文件(二进制大对象)
struct dentry *debugfs_create_blob(const char *name, umode_t mode,
struct dentry *parent,
struct debugfs_blob_wrapper *blob);
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/debugfs.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
static struct dentry *dir = NULL;
static u32 debug_value = 0;
static ssize_t debug_read(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
char buf[32];
int len;
len = snprintf(buf, sizeof(buf), "%u\n", debug_value);
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
}
static ssize_t debug_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, 10, &val))
return -EINVAL;
debug_value = val;
return count;
}
static const struct file_operations debug_fops = {
.read = debug_read,
.write = debug_write,
};
static int __init debug_init(void)
{
// 在debugfs根目录下创建我们的目录
dir = debugfs_create_dir("my_debug", NULL);
if (!dir) {
pr_err("Failed to create debugfs directory\n");
return -ENOMEM;
}
// 在目录中创建一个可读写文件
debugfs_create_file("value", 0644, dir, NULL, &debug_fops);
// 创建一个x32类型的文件
debugfs_create_x32("xvalue", 0644, dir, &debug_value);
pr_info("Debugfs interface initialized\n");
return 0;
}
static void __exit debug_exit(void)
{
// 递归删除整个目录
debugfs_remove_recursive(dir);
pr_info("Debugfs interface removed\n");
}
module_init(debug_init);
module_exit(debug_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Your Name");
MODULE_DESCRIPTION("Debugfs example module");
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/debugfs.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/atomic.h>
static struct dentry *dir = NULL;
static u32 debug_value = 0;
static bool debug_flag = false;
static atomic_t debug_counter = ATOMIC_INIT(0);
// 二进制数据示例
static char debug_blob_data[] = "This is a blob data example";
static struct debugfs_blob_wrapper blob_wrapper = {
.data = debug_blob_data,
.size = sizeof(debug_blob_data),
};
static ssize_t debug_read(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
char buf[32];
int len;
len = snprintf(buf, sizeof(buf), "%u\n", debug_value);
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
}
static ssize_t debug_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, 10, &val))
return -EINVAL;
debug_value = val;
return count;
}
static const struct file_operations debug_fops = {
.read = debug_read,
.write = debug_write,
};
static int __init debug_init(void)
{
// 在debugfs根目录下创建我们的目录
dir = debugfs_create_dir("complex_debug", NULL);
if (!dir) {
pr_err("Failed to create debugfs directory\n");
return -ENOMEM;
}
// 创建各种类型的debugfs文件
debugfs_create_file("value", 0644, dir, NULL, &debug_fops);
debugfs_create_x32("xvalue", 0644, dir, &debug_value);
debugfs_create_bool("flag", 0644, dir, &debug_flag);
debugfs_create_atomic_t("counter", 0644, dir, &debug_counter);
debugfs_create_blob("blob", 0444, dir, &blob_wrapper);
pr_info("Complex debugfs interface initialized\n");
return 0;
}
static void __exit debug_exit(void)
{
debugfs_remove_recursive(dir);
pr_info("Complex debugfs interface removed\n");
}
module_init(debug_init);
module_exit(debug_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Your Name");
MODULE_DESCRIPTION("Complex debugfs example module");
权限管理:
错误处理:
并发控制:
清理工作:
性能考虑:
驱动状态监控:
调试信息输出:
参数动态调整:
故障诊断:
debugfs为Linux驱动开发提供了强大而灵活的调试工具,合理使用可以显著提高驱动开发和调试效率。