参考:
Documentation/filesystems/debugfs.txt
该模块演示了如何使用debugfs来向用户空间导出调试信息。
该模块会在debugfs根部建立如下的文件:
dbgfs_demon/
├── data
└── tracing_on
操作逻辑是,如果 tracing_on的值为Y,那么可以从data中读出有用的调试信息。
如果为N,那么读data操作将不会返回任何数据。
下面是具体的实现代码。
编译和使用:
#echo "obj-m:= dbgfs.o" > Makefile
#make -C /path/to/kernel/tree M=`pwd` modules
#insmod dbgfs.ko
卸载模块
#rmmod dbgfs
挂载debugfs
#mkdir /mnt/debug
#mount -t debugfs nodev /mnt/debug
#cd /mnt/debug/dbgfs_demon
...
// dbgfs.c
/*
* (C) 05-07-2012 Yang Honggang (Joseph), Dslab <[email protected]>
*/
#include <linux/debugfs.h>
#include <linux/module.h>
#include <linux/mm.h>
#include <asm/uaccess.h>
struct dentry *parent, *sw, *inf;
u32 tr_on = 0;
struct my_data_struct {
void* data;
unsigned long size;
} mds;
struct page* pg;
static ssize_t data_read(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
unsigned long i;
size_t cnt;
printk("tr_on:%d\n", tr_on);
/* If the tracing_on is Y, fill the data buffer with debug info */
if (tr_on) {
tr_on = 0; /* Automaticlly clear the 'tracing_on' flag */
for (i = 0; i < (mds.size - 11) / 11; i ++) {
sprintf((char*)((char*)mds.data + i * 11 ), "%ld\n", i + 1000000000);
}
/* Copy debug info to userspace */
cnt = copy_to_user(user_buf, (const void *)mds.data, mds.size);
return (mds.size - cnt);
}
return 0;
}
const struct file_operations fops =
{
.read = data_read,
};
static int __init dbgfs_demon_init(void)
{
printk("dbgfs init\n");
/* Create dbgfs_demon directory in the debugfs root */
parent = debugfs_create_dir("dbgfs_demon", NULL);
if (!parent)
return -1;
/* Create a output switch in dbgfs_demon */
sw = debugfs_create_bool("tracing_on", S_IRWXU,
parent, &tr_on);
if (!sw)
goto p_out;
/* Create a file for debug information exporting */
mds.size = 4 * 1024;
/* Allocate one page for info. storing */
pg = alloc_pages(__GFP_HIGHMEM | __GFP_ZERO, 0);
/* Covert to Memory address */
mds.data = (void*) page_address(pg);
if (!pg)
goto p_out;
inf = debugfs_create_file("data", S_IRUSR,
parent, &mds, &fops);
if (!inf)
goto sw_out;
return 0;
sw_out:
debugfs_remove(sw);
__free_pages(pg, 0);
p_out:
debugfs_remove(parent);
return -1;
}
static void __exit dbgfs_demon_exit(void)
{
if (pg)
__free_pages(pg, 0);
debugfs_remove(inf);
debugfs_remove(sw);
debugfs_remove(parent);
printk("dbgfs exit\n");
return;
}
module_init(dbgfs_demon_init);
module_exit(dbgfs_demon_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Yang Honggang (Joseph) <[email protected]>");