概述
debugfs
是一个Linux内核提供的虚拟文件系统
,旨在为内核开发人员提供一个调试接口。它可以在运行时动态地创建文件和目录
,这些文件和目录与内核数据结构相
关联,以提供对内核信息的实时访问
。通过debugfs
,开发人员可以方便地查看和修改
内核数据结构,例如文件系统
、进程列表
、驱动程序状态
等等。
内核提供了大量的debugfs接口,以便开发人员创建、删除、读取和写入
文件,以及管理文件权限
、所有权
和其他属性。这些接口包括debugfs_create_file
、debugfs_create_dir
、debugfs_create_symlink
等等。
通过debugfs,开发人员可以方便地调试内核问题,以及开发和测试内核驱动程序。它是Linux内核开发和调试的重要工具之一。
Code
file_operations
接口实现- 创建
目录
及文件
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);
节点路径
- 在
/sys/kernel/debug/
目录下创建root/
目录 - 在
root/
下创建dir_x/
和dir_y/
目录 - 分别在
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;
...
}