Linux 创建 debugfs 调试节点

3 篇文章 0 订阅
1 篇文章 0 订阅

概述

debugfs是一个Linux内核提供的虚拟文件系统,旨在为内核开发人员提供一个调试接口。它可以在运行时动态地创建文件和目录,这些文件和目录与内核数据结构相关联,以提供对内核信息的实时访问。通过debugfs,开发人员可以方便地查看和修改内核数据结构,例如文件系统进程列表驱动程序状态等等。

内核提供了大量的debugfs接口,以便开发人员创建、删除、读取和写入文件,以及管理文件权限所有权和其他属性。这些接口包括debugfs_create_filedebugfs_create_dirdebugfs_create_symlink等等。

通过debugfs,开发人员可以方便地调试内核问题,以及开发和测试内核驱动程序。它是Linux内核开发和调试的重要工具之一。

Code

  1. file_operations接口实现
  2. 创建目录文件

file_operations 接口

/* example_node */
static int example_node_show(struct seq_file *m, void *data)
{
	struct my_data *data_param = m->private;
	char info[256] = {0};
	char *s = info;
	int offset = 0;

	offset = sprintf(s, "param_1: %d\n", data_param->param_1);
	offset += sprintf(s + offset, "param_2: %d\n\n", data_param->param_2);

	offset += sprintf(s + offset, "Example of the format to be written:\n");
	offset += sprintf(s + offset, "  `param1=50` (5 <= param1 <= 100)\n");
	offset += sprintf(s + offset, "  `param2=30` (5 <= param1 <= 100)\n");

	seq_printf(m, info);

	return 0;
}

static int example_node_open(struct inode *inode, struct file *file)
{
	struct my_data *data_param = inode->i_private;

	return single_open(file, example_node_show, data_param);
}

static ssize_t example_node_write(struct file *file, const char __user *ubuf,
				       size_t len, loff_t *offp)
{
	struct seq_file *m = file->private_data;
	struct my_data *data_param = m->private;
	char *buf;
	u32 val;
	int offset;
	int ret;

	buf = memdup_user(ubuf, len);
	if (IS_ERR(buf))
		return PTR_ERR(buf);

	/* param1 */
	if (!strncmp(buf, "param1", 6)) {
		offset = 7; // "="

		ret = kstrtou32(buf + offset, 10, &val);
		if (ret)
			return ret;

		if (val < 5 || val > 100) {
			pr_err("Wrong param_1.\n");
			return -EINVAL;
		}

		data_param->param_1 = val;
	}

	/* param2 */
	if (!strncmp(buf, "param2", 6)) {
		offset = 7; // "="

		ret = kstrtou32(buf + offset, 10, &val);
		if (ret)
			return ret;

		if (val < 5 || val > 100) {
			pr_err("Wrong param_2.\n");
			return -EINVAL;
		}

		data_param->param_2 = val;
	}

	kfree(buf);

	return (ret) ? ret : len;
}

static const struct file_operations example_node_fops = {
	.owner = THIS_MODULE,
	.open = example_node_open,
	.read = seq_read,
	.llseek = seq_lseek,
	.release = single_release,
	.write = example_node_write
};

创建目录&文件

struct my_data {
	u32 param_1;
	u32 param_2;
};
struct dentry *root_dentry, *sub_dentry;
struct my_data *data_param = kzalloc(sizeof(struct my_data), GFP_KERNEL);

/* root/ */
root_dentry = debugfs_create_dir("root", NULL); // 参数"NULL",会将目录创建在/sys/kernel/debug/下

/* dir_x/ */
sub_dentry = debugfs_create_dir("dir_x", root_dentry);
/* example_node */
debugfs_create_file("example_node", 0644, sub_dentry, data_param, &example_node_fops);

/* dir_y/ */
sub_dentry = debugfs_create_dir("dir_y", root_dentry);
/* example_node */
debugfs_create_file("example_node", 0644, sub_dentry, data_param, &example_node_fops);

节点路径

  1. /sys/kernel/debug/目录下创建root/目录
  2. root/下创建dir_x/dir_y/目录
  3. 分别在dir_x/dir_y/目录下创建example_node文件节点
root@my-pc:/sys/kernel/debug# tree root/
root/
├── dir_x
│   └── example_node
└── dir_y
    └── example_node

2 directories, 2 files

操作方法

# Read
root@my-pc:/sys/kernel/debug# cat root/dir_x/example_node
param_1: 0
param_2: 0

Example of the format to be written:
  `param1=50` (5 <= param1 <= 100)
  `param2=30` (5 <= param1 <= 100)
# Write
root@my-pc:/sys/kernel/debug# echo param1=20 > root/dir_x/example_node
root@my-pc:/sys/kernel/debug# echo param2=50 > root/dir_x/example_node
root@my-pc:/sys/kernel/debug# cat root/dir_x/example_node
param_1: 20
param_2: 50

Example of the format to be written:
  `param1=50` (5 <= param1 <= 100)
  `param2=30` (5 <= param1 <= 100)

附:关键参数data_param的传递过程

debugfs_create_file时,把data_param存至inode->i_mode

debugfs_create_file("example_node", 0644, sub_dentry, data_param, &example_node_fops);
|- inode->i_private = data_param;

取->存

.open操作时,先从inode->i_mode取出,再存至struct seq_file*private

->static int example_node_open(struct inode *inode, struct file *file)
{
	struct my_data *data_param = inode->i_private; // 取

	return single_open(file, example_node_show, data_param); // 存
	|- ((struct seq_file *)file->private_data)->private = data_param;
}

.read&.write操作时,从struct seq_file*取出。

static int example_node_show(struct seq_file *m, void *data)
{
	struct my_data *data_param = m->private;
	...
}

static ssize_t example_node_write(struct file *file, const char __user *ubuf,
				       size_t len, loff_t *offp)
{
	struct seq_file *m = file->private_data;
	struct my_data *data_param = m->private;
	...
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值