使用debugfs

在前面,我们学习到了sysctl这一基于sysfs和seq_file这一基于procfs文件系统进行交互数据的方式,其中procfs主要是针对进程属性,而sysfs是针对内核模型的,为了保证其稳健,我们很少拿来作为调试时数据交换使用,显然printk也满足不了,那么debugfs就应运而生了.
一般发行版系统会将debugfs挂载在/sys/kernel/debug这一目录下,在/etc/mtab有相关内容,如果没有,也可手动执行如下命令:
mount -t debufgs none /the/debugfs/dir
在include/linux/debugfs.h文件里有debugfs用到的如下函数:
static inline struct dentry *debugfs_create_dir(const char *name, struct dentry *parent);
static inline struct dentry *debugfs_create_file(const char *name, umode_t mode,
struct dentry *parent, void *data, const struct file_operations *fops);
static inline void debugfs_remove(struct dentry *dentry) ;
static inline void debugfs_remove_recursive(struct dentry *dentry) ;
很像前面procfs时的相关函数吧,这就不作解释了,还会用到如下函数:
static inline struct dentry *debugfs_create_u8(const char *name, umode_t mode,
        struct dentry *parent, u8 *value) ;
static inline struct dentry *debugfs_create_u16(const char *name, umode_t mode,
        struct dentry *parent, u16 *value);
static inline struct dentry *debugfs_create_u32(const char *name, umode_t mode,
        struct dentry *parent, u32 *value) ;
static inline struct dentry *debugfs_create_u64(const char *name, umode_t mode,
        struct dentry *parent, u64 *value) ;
这些都是单值文件,还有将上面函数名中的u8、u16、u32、u64替换为x8、x16、x32、x64的函数,这些表示后面的value用16进制数表示。还有size_t、atomic_t、bool等类型的函数,以及跟数组相关的BLOB文件:
static inline struct dentry *debugfs_create_blob(const char *name, umode_t mode,
        struct dentry *parent, struct debugfs_blob_wrapper *blob) ;
还有更多的相关函数请在debugfs.h了解,上面函数中debugfs_blog_wrapper结构体定义如下:
struct debugfs_blob_wrapper {
       void *data;
       unsigned long size;
};
至此,我们了解了相关函数说明,接下来上实例吧:
/*
This module will create debugfs example module,
the directory tree will be created,like:
/sys/kernel/debug (The debugfs mount node)
|_slam_debug
|
|_slam
| |_array
|_array
|_u8
*/
#include <linux/module.h>
#include <linux/debugfs.h>
#include <asm/uaccess.h>

MODULE_LICENSE("GPL");

#define MAX_SLAM_SIZE 32

static struct dentry * slam_debug_dir, * slam_dir;
static u8 u8_var;
static char array[32] = "Hello xinu!\n";
static struct debugfs_blob_wrapper bw;

static int slam_open(struct inode *inode, struct file *filp)
{
        filp->private_data = inode->i_private;
        return 0;
}

static ssize_t slam_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos)
{
        if(*ppos >= MAX_SLAM_SIZE)
                return 0;

        if(*ppos + count > MAX_SLAM_SIZE)
                count = MAX_SLAM_SIZE - *ppos;

        if(copy_to_user(buf, array + *ppos, count))
                return -EFAULT;

        *ppos += count;

        return count;
}

static ssize_t slam_write(struct file *filp, const char __user *buf, size_t count, loff_t *ppos)
{
        if(*ppos >= MAX_SLAM_SIZE)
                return 0;

        if(*ppos + count > MAX_SLAM_SIZE)
                count = MAX_SLAM_SIZE - *ppos;

        if(copy_from_user(array + *ppos, buf, count))
                return -EFAULT;

        *ppos += count;

        return count;
}

static struct file_operations slam_array_fops =
{
        .owner = THIS_MODULE,
        .open = slam_open,
        .read = slam_read,
        .write = slam_write,
};

static int __init debugfs_example_init(void)
{
        slam_debug_dir = debugfs_create_dir("slam_debug", NULL);

        bw.data = (void *)array;
        bw.size = strlen(array) + 1;
        debugfs_create_blob("array", 0644, slam_debug_dir, &bw);

        slam_dir = debugfs_create_dir("slam", slam_debug_dir);
        debugfs_create_u8("u8", 0644, slam_debug_dir, &u8_var);
        debugfs_create_file("array", 0644, slam_dir, NULL, &slam_array_fops);

        return 0;
}

static void __exit debugfs_example_exit(void)
{
        debugfs_remove_recursive(slam_debug_dir);
}

module_init(debugfs_example_init);
module_exit(debugfs_example_exit);
相应的Makefile内容如下:
obj-m += debugfs_example.o

CUR_PATH:=$(shell pwd)
LINUX_KERNEL_PATH:=/home/xinu/linux-3.13.6

all:
        make -C $(LINUX_KERNEL_PATH) M=$(CUR_PATH) modules

clean:
        make -C $(LINUX_KERNEL_PATH) M=$(CUR_PATH) clean
相应的源码文件目录树如下:
/home/xinu/xinu/linux_kernel_driver_l1/debugfs_example/
├── debugfs_example.c
└── Makefile
编译加载KO后,在/sys/kernel/debug目录下就会生成相应的目录和文件节点,相关目录树在源码里有说明。至此,我们对Debugfs也进行了了解。
参考网址:
http://www.embeddedlinux.org.cn/html/yingjianqudong/201304/17-2553.html
http://www.cnblogs.com/wwang/archive/2011/01/17/1937609.html
https://www.ibm.com/developerworks/cn/linux/l-kerns-usrs2/

评论

此博客中的热门博文

I/O映射之I/O端口

通过Netlink检测网线插拔

使用seq_file