本文共 2115 字,大约阅读时间需要 7 分钟。
最常用的内核调试手段是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);
子目录也是用debugfs_create_dir来实现
sub_dir = debugfs_create_dir(
"subdir"
, my_debugfs_root);
建立文件a的代码非常简单:
debugfs_create_u8(
"a"
, 0644, my_debugfs_root, &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。转载地址:http://pedmi.baihongyu.com/