Linux内核空间-用户空间通信之debugfs
生活随笔
收集整理的這篇文章主要介紹了
Linux内核空间-用户空间通信之debugfs
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
一、debugfs文件系統(tǒng)簡介
debugfs虛擬文件系統(tǒng)是一種內(nèi)核空間與用戶空間的接口,基于libfs庫實現(xiàn),專用于開發(fā)人員調(diào)試,便于向用戶空間導(dǎo)出內(nèi)核空間數(shù)據(jù)(當然,反方向也可以)。debugfs在linux內(nèi)核版本2.6.10引入,作者是Greg Kroah-Hartman。 與procfs和sysfs不同,前者主要提供進程信息(當然后來又加入設(shè)備、內(nèi)存、網(wǎng)絡(luò)等信息,比較雜亂),后者主要提供設(shè)備信息,且有一個文件提供一個值的“規(guī)則”,是Linux通用設(shè)備模型的影射。debugfs沒有類似的限制,開發(fā)者可以放入任何信息。二、debugfs的使用
說明:函數(shù)接口請參見:http://docs.huihoo.com/doxygen/linux/kernel/3.7/fs_2debugfs_2file_8c.html#ad5e6fa7f4a3de8d751a7fff4d99e59f31. 掛載debugfs文件系統(tǒng)
要使用debugfs,需要在內(nèi)核編譯配置中配置CONFIG_DEBUG_FS選項,一般的發(fā)行版都會默認編譯進了內(nèi)核,并且將其自動掛載默認的目錄(/sys/kernel/debug),可通過以下命令查看: 也可手動掛載到其它位置: $ mkdir /debugfs $ mount -t debugfs none /debugfs2. 利用debugfs導(dǎo)出基本數(shù)據(jù)類型的變量
debugfs可以將內(nèi)核中基本整數(shù)類型的變量導(dǎo)出為單個文件,在用戶空間中可以直接對其讀寫(如使用cat、echo命令),只要權(quán)限允許即可。支持的類型有:u8, u16, u32, u64, size_t和 bool。其中bool類型在內(nèi)核中要定義為u32類型,在用戶空間中對應(yīng)的文件內(nèi)容則顯示為Y或N。示例代碼如下: static struct dentry *root_d = debugfs_create_dir("exam_debugfs", NULL); //在debugfs根目錄下創(chuàng)建新目錄exam_debugfs,然會新建目錄的目錄項指針 static u8 var8; debugfs_create_u8("var-u8", 0664, root_d, &var8); //在exam_debugfs中創(chuàng)建變量var8對應(yīng)的文件,名為var-u8,權(quán)限為0664 static u32 varbool; debugfs_create_bool("var-bool", 0664, root_d, &varbool); //bool變量3. 利用debugfs導(dǎo)出數(shù)據(jù)塊(只讀)
debugfs提供的debugfs_create_blob函數(shù)可導(dǎo)出數(shù)據(jù)塊,示例代碼如下: char buf[] = "Hello debugfs!\n"; b.data = buf; b.size = strlen(buf) + 1; debugfs_create_blob("blob", 0644, root_d, &b); // blob is readonly, even if 0644 沒錯,debugfs提供的debugfs_blob_wrapper結(jié)構(gòu)所導(dǎo)出的數(shù)據(jù)塊只能讀取,不能修改。4. 利用debugfs導(dǎo)出u32數(shù)組(只讀)
debugfs提供的debugfs_create_u32_array函數(shù)可導(dǎo)出內(nèi)核中u32類型的數(shù)組。示例代碼如下: u32 arr[] = {1,2,3,4,5}; debugfs_create_u32_array("array", 0664, root_d, arr, sizeof(arr)/sizeof(u32));5. 實現(xiàn)可讀寫數(shù)據(jù)塊的導(dǎo)出
實現(xiàn)并不難,只需實現(xiàn)struct file_operations的open、write、read方法即可。然后調(diào)用debugfs提供的debugfs_create_file即可。該方法的原型如下: struct dentry* debugfs_create_file ( const char * name,umode_t mode,struct dentry * parent,void * data, // 傳入的data指針會被賦值給新建文件對應(yīng)inode的i_private字段const struct file_operations * fops ) 下面,仿照struct?debugfs_blob_wrapper的實現(xiàn),實現(xiàn)struct my_blob_wrapper和my_blob_wrapper_ops,提供可讀寫的“blob”: /** 自定義可讀寫blob **/ struct my_blob_wrapper{void *data;unsigned long size; // data緩沖區(qū)長度 }; static int my_blob_wrapper_open(struct inode *inode, struct file *filp) {filp->private_data = inode->i_private; // inode->i_private被設(shè)置為debugfs_create_file傳入的data參數(shù)return 0; } static ssize_t my_blob_wrapper_read(struct file *filp, char __user *user_buf, size_t count, loff_t *ppos) {struct my_blob_wrapper *blob = filp->private_data;return simple_read_from_buffer(user_buf, count, ppos,blob->data, blob->size);//此函數(shù)有l(wèi)ibfs提供,與下面邏輯等價 // if (*ppos >= blob->size) { // return 0; // } // if (*ppos + count > blob->size) { // count = blob->size - *ppos; // } // if (copy_to_user(user_buf, blob->data + *ppos, count) != 0) { // return -EFAULT; // } // *ppos += count; // return count; } static ssize_t my_blob_wrapper_write(struct file *filp, const char __user *user_buf, size_t count, loff_t *ppos) {struct my_blob_wrapper *blob = filp->private_data;return simple_write_to_buffer(blob->data, blob->size, ppos,user_buf, count);//此函數(shù)由libfs提供,與下面邏輯等價 // if (*ppos >= blob->size) { // return 0; // } // if (*ppos + count > blob->size) { // count = blob->size - *ppos; // } // if (copy_from_user(blob->data + *ppos, user_buf, count) != 0) { // return -EFAULT; // } // *ppos += count; // return count; } static struct file_operations my_blob_wrapper_ops = {.owner = THIS_MODULE,.open = my_blob_wrapper_open,.read = my_blob_wrapper_read,.write = my_blob_wrapper_write,.llseek = default_llseek,//VFS提供 }; struct dentry *my_create_blob(const char *name, umode_t mode,struct dentry *parent,struct my_blob_wrapper *blob) {return debugfs_create_file(name, mode, parent, blob, &my_blob_wrapper_ops); } /* done */6. 注意:
① 在debugfs中創(chuàng)建的文件和目錄在模塊退出時,并不會自動刪除,可調(diào)用debugfs_remove_recursive刪除整個目錄,或調(diào)用debugfs_remove刪除單個文件。 ② u32_array在用戶空間文件中顯示為空格隔開的元素 ③?debugfs_create_x{8,16,32,64}與debugfs_create_u{8,16,32,64}的不同在于前者顯示為16進制,后者顯示為10進制三、debugfs示例完整代碼
#include <linux/module.h> #include <linux/debugfs.h> #include <linux/fs.h> // for libfs #include <asm-generic/uaccess.h>/** 自定義可讀寫blob **/ struct my_blob_wrapper{void *data;unsigned long size; }; static int my_blob_wrapper_open(struct inode *inode, struct file *filp) {filp->private_data = inode->i_private;return 0; } static ssize_t my_blob_wrapper_read(struct file *filp, char __user *user_buf, size_t count, loff_t *ppos) {struct my_blob_wrapper *blob = filp->private_data;return simple_read_from_buffer(user_buf, count, ppos, blob->data, blob->size); // from libfs } static ssize_t my_blob_wrapper_write(struct file *filp, const char __user *user_buf, size_t count, loff_t *ppos) {struct my_blob_wrapper *blob = filp->private_data;return simple_write_to_buffer(blob->data, blob->size, ppos, user_buf, count); } static struct file_operations my_blob_wrapper_ops = {.owner = THIS_MODULE,.open = my_blob_wrapper_open,.read = my_blob_wrapper_read,.write = my_blob_wrapper_write,.llseek = default_llseek, // from vfs }; /* 接口函數(shù) */ struct dentry *my_create_blob(const char *name, umode_t mode,struct dentry *parent,struct my_blob_wrapper *blob) {return debugfs_create_file(name, mode, parent, blob, &my_blob_wrapper_ops); } /** my_clob implementation end **/static struct dentry *root_d; static u8 var8; static u16 var16; static u32 var32; static u32 varbool; static char buf[] = "Hello debugfs!\n"; static struct debugfs_blob_wrapper b; static struct my_blob_wrapper b2; static u32 arr[] = {1,2,3,4,5};int __init mod_init(void) {printk(KERN_INFO "exam_debugfs: initialing...\n");root_d = debugfs_create_dir("exam_debugfs", NULL);if (!root_d) {printk(KERN_INFO "exam_debugfs: error create root dir\n");return 1;}/* u{8,16,32}, bool */debugfs_create_u8("var-u8", 0664, root_d, &var8);debugfs_create_u16("var-u16", 0664, root_d, &var16);debugfs_create_u32("var-u32", 0664, root_d, &var32);debugfs_create_bool("var-bool", 0664, root_d, &varbool);/* u32_array */debugfs_create_u32_array("array", 0664, root_d, arr, sizeof(arr)/sizeof(u32));/* blob_wrapper */b.data = buf;b.size = strlen(buf) + 1;debugfs_create_blob("blob", 0644, root_d, &b); // blob is readonly, even if 0644/* my_blob_wrapper */b2.data = buf;b2.size = strlen(buf) + 1;my_create_blob("myblob", 0644, root_d, &b2);return 0; } void __exit mod_exit(void) {debugfs_remove_recursive(root_d);printk(KERN_INFO "exam_debugfs: exiting...\n"); }module_init(mod_init); module_exit(mod_exit);MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("a demo for debugfs"); MODULE_AUTHOR("rsljdkt");四、補充:debugfs bool的實現(xiàn)
static ssize_t read_file_bool(struct file *file, char __user *user_buf,size_t count, loff_t *ppos) {char buf[3];u32 *val = file->private_data;if (*val)buf[0] = 'Y';elsebuf[0] = 'N';buf[1] = '\n';buf[2] = 0x00;return simple_read_from_buffer(user_buf, count, ppos, buf, 2); }static ssize_t write_file_bool(struct file *file, const char __user *user_buf,size_t count, loff_t *ppos) {char buf[32];size_t buf_size;bool bv;u32 *val = file->private_data;buf_size = min(count, (sizeof(buf)-1));if (copy_from_user(buf, user_buf, buf_size))return -EFAULT;if (strtobool(buf, &bv) == 0)*val = bv;return count; }參考: Debugfs? http://en.wikipedia.org/wiki/Debugfs
Function Documentation? http://docs.huihoo.com/doxygen/linux/kernel/3.7/fs_2debugfs_2file_8c.html#ad5e6fa7f4a3de8d751a7fff4d99e59f3
Linux內(nèi)核里的DebugFS? http://www.cnblogs.com/wwang/archive/2011/01/17/1937609.html
header file:? http://lxr.free-electrons.com/source/include/linux/debugfs.h
?
新人創(chuàng)作打卡挑戰(zhàn)賽發(fā)博客就能抽獎!定制產(chǎn)品紅包拿不停!總結(jié)
以上是生活随笔為你收集整理的Linux内核空间-用户空间通信之debugfs的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: SQLSERVER压缩数据文件的用处有多
- 下一篇: Red Hat Linux 253 实验