// DebugFS:
// 默认情况下,debugfs会被挂载在目录/sys/kernel/debug
// 手动挂载,mount -t debugfs none /your/debugfs/dir
// 创建目录/文件:
struct dentry *debugfs_create_dir(const char *name, struct dentry *parent);
struct dentry *debugfs_create_file(const char *name, mode_t mode,
struct dentry *parent, void *data,
const struct file_operations *fops);
// 删除目录/文件
void debugfs_remove(struct dentry *dentry);
// 删除目录下所有dentry
void debugfs_remove_recursive(struct dentry *dentry);
// 创建单值对象:
struct dentry *debugfs_create_u8(const char *name, mode_t mode,
struct dentry *parent, u8 *value);
struct dentry *debugfs_create_u16(const char *name, mode_t mode,
struct dentry *parent, u16 *value);
struct dentry *debugfs_create_u32(const char *name, mode_t mode,
struct dentry *parent, u32 *value);
struct dentry *debugfs_create_u64(const char *name, mode_t mode,
struct dentry *parent, u64 *value);
struct dentry *debugfs_create_x8(const char *name, mode_t mode,
struct dentry *parent, u8 *value);
struct dentry *debugfs_create_x16(const char *name, mode_t mode,
struct dentry *parent, u16 *value);
struct dentry *debugfs_create_x32(const char *name, mode_t mode,
struct dentry *parent, u32 *value);
struct dentry *debugfs_create_size_t(const char *name, mode_t mode,
struct dentry *parent, size_t *value);
struct dentry *debugfs_create_bool(const char *name, mode_t mode,
struct dentry *parent, u32 *value);
// 创建二进制对象:
struct debugfs_blob_wrapper {
void *data;
unsigned long size;
};
struct dentry *debugfs_create_blob(const char *name, mode_t mode,
struct dentry *parent, struct debugfs_blob_wrapper *blob);
// 其他:
struct dentry *debugfs_rename(struct dentry *old_dir, struct dentry *old_dentry,
struct dentry *new_dir, const char *new_name);
struct dentry *debugfs_create_symlink(const char *name,
struct dentry *parent, const char *target);
// 简单封装debugfs,实现对内核缓存区的读访问,方便调试驱动观察缓存区:
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/debugfs.h>
struct debug_struct
{
void *buffer;
int buffer_len;
struct dentry *file;
};
static int debug_open(struct inode *inode, struct file *filp)
{
filp->private_data = inode->i_private;
return 0;
}
static ssize_t debug_read(struct file *fp, char __user *user_buffer,
size_t count, loff_t *position)
{
struct debug_struct *s = (struct debug_struct *)fp->private_data;
return simple_read_from_buffer(user_buffer, count, position, s->buffer, s->buffer_len);
}
const struct file_operations debug_fops = {
.read = debug_read,
.open = debug_open,
};
static int debug_create_file(struct dentry *dir, struct debug_struct *st, const char *name)
{
if(!st)
return -EINVAL;
st->file = debugfs_create_file(name, 0644, dir, st, &debug_fops);
if(!st->file)
return -ENODEV;
return 0;
}
static int debug_remove_file(struct debug_struct *st)
{
if(!st)
return -EINVAL;
debugfs_remove(st->file);
st->file = NULL;
return 0;
}
// 测试:
// 1.创建核心内存mem
// 2.通过debugfs,创建mem的文件
#define BUFFER_SIZE 1024
struct debug_struct *st;
struct dentry *dir;
static void debug_init(void)
{
int ret = 0;
st = (struct debug_struct *)kmalloc(sizeof(struct debug_struct), GFP_KERNEL);
if(!st)
{
printk(KERN_ALERT "debug test: kmalloc debug_struct failed.\n");
goto err_kmalloc_st;
}
st->buffer = kmalloc(BUFFER_SIZE, GFP_KERNEL);
if(!st->buffer)
{
printk(KERN_ALERT "debug test: kmalloc buffer failed.\n");
goto err_kmalloc_buff;
}
st->buffer_len = BUFFER_SIZE;
dir = debugfs_create_dir("debug_dir", NULL);
if(!dir)
{
printk(KERN_ALERT "debug test: debugfs_create_dir failed.\n");
goto err_create_dir;
}
ret = debug_create_file(dir, st, "debug_mem");
if(ret)
{
printk(KERN_ALERT "debug test: debug_create_file failed.\n");
goto err_create_file;
}
//now you can see debug_dir in /sys/kernel/debug/
return;
err_create_file:
debugfs_remove_recursive(dir);
err_create_dir:
kfree((void *)st->buffer);
err_kmalloc_buff:
kfree((void *)st);
err_kmalloc_st:
return;
}
static void debug_uinit(void)
{
int ret = 0;
debug_remove_file(st);
debugfs_remove_recursive(dir);
kfree((void *)st->buffer);
kfree((void *)st);
return;
}
// 参考:
// http://www.linuxforu.com/2010/10/debugging-linux-kernel-with-debugfs/
// http://www.cnblogs.com/wwang/archive/2011/01/17/1937609.html