linux内核 DebugFS

Linux下的Debugfs 调试操作 阅读详情

一、简介

DebugFS,顾名思义,是一种用于内核调试的虚拟文件系统,内核开发者通过debugfs和用户空间交换数据。类似的虚拟文件系统还有procfs和sysfs等,这几种虚拟文件系统都并不实际存储在硬盘上,而是Linux内核运行起来后才建立起来。

通常情况下,最常用的内核调试手段是printk。我们在调试时可能需要修改某些内核变量,这种情况下printk就无能为力,而如果为了修改某个值重新编译内核或者驱动又过于低效,此时就需要一个临时的文件系统可以把我们需要关心的数据映射到用户空间。不论是procfs或是sysfs,用它们来实现某些debug的需求,似乎偏离了它们创建的本意。比如procfs,其目的是反映进程的状态信息;而sysfs主要用于linux设备模型。不论是procfs或是sysfs的接口应该保持相对稳定,因为用户态程序很可能会依赖它们。当然,如果我们只是临时借用procfs或者sysfs来作debug之用,在代码发布之前将相关调试代码删除也无不可。但如果相关的调试借口要在相当长的一段时间内存在于内核之中,就不太适合放在procfs和sysfs里了。故此,debugfs应运而生。

默认情况下,debugfs会被挂载在目录/sys/kernel/debug之下,如果你的发行版里没有自行挂载,可以用下面命令手动完成:

mount -t debugfs none /sys/kernel/debug


二、打开debugfs选项

要使用debugfs,首先我们要设置一下配置选项CONFIG_DEBUG_FS,可以在config文件中设置CONFIG_DEBUG_FS=y,也可以通过menuconfig来设置

Kernelhacking --->

                          [*]Debug Filesystem

并且驱动中使用debugfs需要包含头文件<linux/debugfs.h>,为了在用户态下使用debugfs,必须把它mount到一个目录下


三、Llinux内核为debugfs提供了非常简洁的API:

debugfs
|--mydebug

   |--subdir

      c

   a

   b


1、创建和撤销目录及文件

1)structdentry *debugfs_create_dir(constchar*name,struct dentry *parent);
第一个参数是目录的名称,第二个参数是指定这个目录的上级目录,如果是NULL,表示放在debugfs的根目录下
my_debugfs_root = debugfs_create_dir("mydebug", NULL);
sub_dir = debugfs_create_dir("subdir", my_debugfs_root);
debugfs
|--mydebug
   |--subdir


2)structdentry *debugfs_create_file(constchar*name, mode_t mode,structdentry *parent,void*data,conststruct file_operations *fops);
文件c通过自定义的文件操作实现读写
debugfs
|--mydebug
   |--subdir
      c
[cpp]  view plain  copy
  1. static int c_open(struct inode *inode, struct file *filp)  
  2. {  
  3.     filp->private_data = inode->i_private;  
  4.     return 0;  
  5. }  
  6.    
  7. static ssize_t c_read(struct file *filp, char __user *buffer,  
  8.         size_t count, loff_t *ppos)  
  9. {  
  10.     if (*ppos >= 32)  
  11.         return 0;  
  12.     if (*ppos + count > 32)  
  13.         count = 32 - *ppos;  
  14.    
  15.     if (copy_to_user(buffer, hello + *ppos, count))  
  16.         return -EFAULT;  
  17.    
  18.     *ppos += count;  
  19.    
  20.     return count;  
  21. }  
  22.    
  23. static ssize_t c_write(struct file *filp, const char __user *buffer,  
  24.         size_t count, loff_t *ppos)  
  25. {  
  26.     if (*ppos >= 32)  
  27.         return 0;  
  28.     if (*ppos + count > 32)  
  29.         count = 32 - *ppos;  
  30.    
  31.     if (copy_from_user(hello + *ppos, buffer, count))  
  32.         return -EFAULT;  
  33.    
  34.     *ppos += count;  
  35.    
  36.     return count;  
  37. }  
  38.    
  39. struct file_operations c_fops = {  
  40.     .owner = THIS_MODULE,  
  41.     .open = c_open,  
  42.     .read = c_read,  
  43.     .write = c_write,  
  44. };  
  45.    
  46.    
  47. debugfs_create_file("c", 0644, sub_dir, NULL, &c_fops);  

3)voiddebugfs_remove(structdentry *dentry);
4)voiddebugfs_remove_recursive(struct dentry *dentry);
在module_exit中,我们要释放创建的数据
debugfs_remove_recursive(my_debugfs_root);
这个函数可以帮我们逐步移除每个分配的dentry,如果你想要一个个手动移除,也可以直接调用debugfs_remove

2、创建单值文件
1)structdentry *debugfs_create_u8(constchar*name, mode_t mode,struct dentry *parent, u8 *value);
debugfs_create_u8("a", 0644, my_debugfs_root, &a);
debugfs
|--mydebug
   |--subdir
   a
创建的文件名是a,对应内核中的变量名为a,文件属性为0644,可以对文件读写,相当于是对内核变量读写。

2)structdentry *debugfs_create_u16(constchar*name, mode_t mode,structdentry *parent, u16 *value);
3)structdentry *debugfs_create_u32(constchar*name, mode_t mode,structdentry *parent, u32 *value);
4)structdentry *debugfs_create_u64(constchar*name, mode_t mode,structdentry *parent, u64 *value);
其中,后缀为x8、x16、x32的这三个函数是指debugfs中的数据用十六进制表示。 
5)structdentry *debugfs_create_x8(constchar*name, mode_t mode,structdentry *parent, u8 *value);
6)structdentry *debugfs_create_x16(constchar*name, mode_t mode,structdentry *parent, u16 *value);
7)structdentry *debugfs_create_x32(constchar*name, mode_t mode,structdentry *parent, u32 *value);
8)structdentry *debugfs_create_size_t(constchar*name, mode_t mode,structdentry *parent,size_t*value);
9)structdentry *debugfs_create_bool(constchar*name, mode_t mode,struct dentry *parent, u32 *value);

3、创建BLOB文件
structdebugfs_blob_wrapper {
    void*data;
    unsignedlongsize;
};
structdentry *debugfs_create_blob(constchar*name, mode_t mode,structdentry *parent,struct debugfs_blob_wrapper *blob);
char hello[32] = "hello world!\n";
struct debugfs_blob_wrapper b;
b.data = (void *)hello;
b.size = strlen(hello) + 1;
debugfs_create_blob("b", 0644, my_debugfs_root, &b);
debugfs
|--mydebug
   |--subdir
   b
需要注意的是blob wrapper定义的数据只能是只读的,在本例中我们将文件b的权限设定为0644,但实际这个文件还是只读的,
如果试图改写这个文件,系统将提示出错。
因此,如果我们要对内核数组进行读写动作,blob wrapper就无法满足要求,我们只能自己定义文件操作来实现。

4、其他
structdentry *debugfs_rename(structdentry *old_dir,structdentry *old_dentry,structdentry *new_dir,constchar*new_name);
structdentry *debugfs_create_symlink(constchar*name,structdentry *parent,constchar *target);

以上部分转自:http://www.cnblogs.com/wwang/archive/2011/01/17/1937609.html


三、实例
这个实例虽然简单,但是融合了如何在debugfs目录下创建文件,并给出了文件的操作方法;
也说明了如何创建变量文件,并且用户空间读写这个变量文件相当于是在读写内核空间的这个文件对应的变量
[cpp]  view plain  copy
  1. // dbgfs.c   
  2. /* 
  3.  * (C) 05-07-2012 Yang Honggang (Joseph), Dslab <eagle.rtlinux@gmail.com> 
  4.  */  
  5. #include <linux/debugfs.h>  
  6. #include <linux/module.h>  
  7. #include <linux/mm.h>  
  8. #include <asm/uaccess.h>   
  9.   
  10. struct dentry *parent, *sw, *inf;  
  11. u32 tr_on = 0;  
  12.   
  13. struct my_data_struct {  
  14.     void* data;  
  15.     unsigned long size;  
  16. } mds;  
  17.   
  18. struct page* pg;  
  19.   
  20. static ssize_t data_read(struct file *file, char __user *user_buf,size_t count, loff_t *ppos)  
  21. {  
  22.     unsigned long i;  
  23.     size_t cnt;  
  24.      
  25.     printk("tr_on:%d\n", tr_on);  
  26.     /* If the tracing_on is Y, fill the data buffer with debug info */  
  27.     if (tr_on) {  
  28.         tr_on = 0; /* Automaticlly clear the 'tracing_on' flag */  
  29.                 for (i = 0; i < (mds.size - 11) / 11; i ++) {  
  30.                 sprintf((char*)((char*)mds.data + i * 11 ), "%ld\n", i + 1000000000);  
  31.         }  
  32.           
  33.         /* Copy debug info to userspace */  
  34.         cnt = copy_to_user(user_buf, (const void *)mds.data, mds.size);  
  35.         return (mds.size - cnt);  
  36.     }  
  37.      
  38.     return 0;  
  39. }  
  40.   
  41. const struct file_operations fops =  
  42. {  
  43.         .read = data_read,  
  44. };  
  45.   
  46. static int __init dbgfs_demon_init(void)  
  47. {  
  48.   
  49.     printk("dbgfs init\n");   
  50.     /* Create dbgfs_demon directory in the debugfs root */  
  51.     parent = debugfs_create_dir("dbgfs_demon", NULL);  
  52.     if (!parent)   
  53.     return -1;     
  54.   
  55. //在debugfs目录下创建变量名tracing_on,对应内核中的变量tr_on  
  56.     /* Create a output switch in dbgfs_demon */  
  57.     sw = debugfs_create_bool("tracing_on", S_IRWXU,parent, &tr_on);   
  58.     if (!sw)  
  59.     goto p_out;  
  60.       
  61.     /* Create a file for debug information exporting */  
  62.     mds.size = 4 * 1024;      
  63.     /* Allocate one page for info. storing */  
  64.     pg = alloc_pages(__GFP_HIGHMEM | __GFP_ZERO, 0);  
  65.     /* Covert to Memory address */  
  66.     mds.data = (void*) page_address(pg);  
  67.     if (!pg)  
  68.     goto p_out;  
  69.   
  70. //在debugfs目录下创建文件名data,对应的文件操作为fops里面的read和write方法,  
  71. //通过read函数中从用户空间传来的buf进行相应的处理。  
  72.     inf = debugfs_create_file("data", S_IRUSR,parent, &mds, &fops);  
  73.     if (!inf)  
  74.     goto sw_out;  
  75.   
  76.     return 0;  
  77.   
  78. sw_out:  
  79.     debugfs_remove(sw);  
  80.     __free_pages(pg, 0);  
  81. p_out:  
  82.     debugfs_remove(parent);  
  83.   
  84.     return -1;  
  85. }  
  86.   
  87. static void __exit dbgfs_demon_exit(void)  
  88. {  
  89.   
  90.     if (pg)  
  91.     __free_pages(pg, 0);  
  92.   
  93.     debugfs_remove(inf);  
  94.     debugfs_remove(sw);  
  95.     debugfs_remove(parent);  
  96.     printk("dbgfs exit\n");  
  97.   
  98.     return;  
  99. }  
  100.   
  101. module_init(dbgfs_demon_init);    
  102. module_exit(dbgfs_demon_exit);    
  103. MODULE_LICENSE("GPL");    
  104. MODULE_AUTHOR("Yang Honggang (Joseph) <eagle.rtlinux@gmail.com>");  
模块会在/sys/kernel/debugfs根目录下创建
dbgfs_demon/
|--data
|--tracing_on
函数的操作逻辑是,如果tracing_on的值为Y,那么可以从文件data中读出有用的调试信息,
如果为N,那么读data操作将不会返回任何数据。

另外还有一个网上找到的debugfs的小例子: http://download.youkuaiyun.com/detail/luckywang1103/9369310
原文链接:http://blog.youkuaiyun.com/luckywang1103/article/details/26809843
【linux kernel】linux内核中的debugfs 本文分析和讨论linux内核中debugfs常用的API和使用方法。 阅读详情

相关推荐

Linux: config: DEBUG_FS

很多内核模块会有方便调试的工具,比如:i40e驱动的debug命令。/sys/kernel/debug,目录系统是在;

mzhan017的博客 778

Linux 内核debugfs总结

Debugfs 是内核开发人员向用户空间提供信息的一种简单方法。/proc 仅用于提供有关进程的信息,或者 sysfs 具有严格的每个文件一个值的规则,而 debugfs 则完全没有规则。开发人员可以将他们想要的任何信息放在那里。debugfs 文件系统也不能作为用户空间的稳定 ABI;理论上,在那里导出的文件没有稳定性限制。现实世界并不总是那么简单,即使是 debugfs 接口,最好的设计也是考虑到它们需要永远维护。(或等效的 /etc/fstab 行)。

uunubt的专栏 4792

GIS分析-利用K-Means方法进行地震分析

通过“聚类”可以获得有关我们所拥有的数据的各种线索,这是数据挖掘技术之一。分析创建的组有助于决策过程。在这项研究中,我们将使用数据挖掘工具之一的K-Means方法研究安纳托利亚东部地区近100年发生的地震的空间分布,并试图获得有用的信息,以供未来的研究使用。我从局地震目录页面获得了研究所需的地震数据,并从获得了区域边界数据。

gis收藏家的博客 1570

Linux内核里的DebugFS

DebugFS,顾名思义,是一种用于内核调试的虚拟文件系统,内核开发者通过debugfs和用户空间交换数据。类似的虚拟文件系统还有procfs和sysfs等,这几种虚拟文件系统都并不实际存储在硬盘上,而是Linux内核运行起来后才建立起来。 通常情况下,最常用的内核调试手段是printk。但printk并不是所有情况都好用,比如打印的数据可能过多,我们真正关心的数据在大量的输出里不是那么一目了然...

weixin_30571465的博客 1579

ZYNQ新手必看:你的PS端DDR和QSPI配置真的对了吗?从原理到实操的避雷指南

本文深入解析ZYNQ PS端外设配置的关键要点,特别是DDR匹配和QSPI时钟优化的实战技巧。通过详细案例和配置清单,帮助开发者避免常见错误,确保系统稳定性和启动可靠性。适合ZYNQ新手和需要优化最小系统的开发者参考。

weixin_28675839的博客 445

【原创】SAP/Oracle 集团企业海外全球化实施注意事项: 一带一路本地化 (持续更新)...

ABC集团SAP的系统平台已经扩展到全球一百来个国家和地区,SAP系统平台的全球实施项目中, 当时是需要支持当地的业务和法律法规的合规要求。   当时客户也是缺乏当地的资源以及对当地法律法规和业务实践的了解,需要团队提供了全球化的支持,通过我们全球产品技术专家充分传递了各区域的本地化支持和实践 而且近年来我们发现一些国家和政府,陆续都在推出一些新的税改和合规的要求,接下来基于这些要求,我们全球...

weixin_34024034的博客 1143

Linux内核调试debugfs

DebugFS,顾名思义,是一种用于内核调试的虚拟文件系统,内核开发者通过debugfs和用户空间交换数据。类似的虚拟文件系统还有procfs和sysfs等,这几种虚拟文件系统都并不实际存储在硬盘上,而是Linux内核运行起来后才建立起来。 通常情况下,最常用的内核调试手段是printk。但printk并不是所有情况都好用,比如打印的数据可能过多,我们真正关心的数据在大量的输出里不是那么一目了然...

lemontree1945的博客 425

[终于解决]Ubuntu14.04 32位安装移动网卡(0bda:b711)驱动8188gu tplink-WN726n

大致梳理一下问题解决的流程 首先,在台式机做了双系统,台式机只有一个网线接口,由于项目要求,需要占用网口传输数据,所以用之前买的tplink-WN726n免驱版2.0的移动网卡 【note】免驱版只能在Windows下安装使用,在Ubuntu系统中无法使用,所以,需要另辟蹊径。 找了很多资料,尝试很多方法,有的复杂有的简单,终于解决。 【思路】首先在Ubuntu系统中输入lsusb,查看是否检测到USB网卡设备。然后从Github中复制代码,构建,安装,然后modprobe一下,到前面那步还不行,就再来一步

瑞o 1万+

Linux内核学习10--debugfs

最后才说是挂载debugfs,然后修改里面的regman即可。之前看驱动的时候,不少驱动提供了在sysfs的接口,而且也看了怎么创建。所以先看看这个和sysfs,还有procfs的区别。提供基本的 GPIO 控制接口,允许用户导出 GPIO 引脚、设置输入/输出方向、读取/写入引脚电平。主要用于调试,显示所有 GPIO 引脚的状态信息,包括引脚方向、值、驱动程序分配情况等。今天在debugfs里面也看到了。位于 /sys/kernel/debug/gpio。位于 /sys/class/gpio/。

fanged的专栏 467

Blender.粒子效果

Blender.粒子效果 ✦ shift+A新建一个棱角球,细分(之后要分解成许多小颗粒) ✦ 给球添加粒子系统,这时播放粒子会向下掉,力场权重☛重力☛0后,粒子会在球体周围运动 ✦ shift+A添加一个力场,调整力场强度 ✦如果粒子运动太快,我们可以在输出属性中调整时间重映射的原始值 ✦想让粒子在球周围运动而不是发散出去,在物理属性找到力场设置,调整流的大小 ✦S键将球形缩小到看不见 ✦给粒子变添加立方体的形状,在粒子属性里找到渲染选项,将“光晕”改为“物体”,在实例物体中选择新建的立方

weixin_46385629的博客 6669

FlashBootloader01-基于UDS的Flash Bootloader【架构篇】

文章目录1 Flash Bootloader的依赖项2 Flash Bootloader中使用的UDS的主要功能3 Flash Bootloader更新固件3.1 初始化MCU3.2 刷写流程 1 Flash Bootloader的依赖项 通常Flash Bootloader由以下四方面组成: UDS协议 上位机「编写Bootloader Sequence」 通信驱动(如CAN ) Flash Driver 2 Flash Bootloader中使用的UDS的主要功能 1. 10 02服务 客户端

3591

Linux内核开启DebugFS以及查看debug信息(/sys/kernel/debug及debugfs)

一、Linux内核开启DebugFS 进入内核配置界面,查找DebugFS: 开启配置: 二、Linux内核挂载DebugFS mount -t debugfs none /sys/kernel/debug/ 三、查看debug信息 所有debug信息都在/sys/kernel/debug/路径中。 比如查看当前gpio使用情况: ...

Mculover666的博客(嵌入式) 1万+

YOLOv8【第一章:基础入门篇·第1节】一文搞定,核心架构深度解析与环境配置!

🏆 本文收录于 《YOLOv8实战:从入门到深度优化》 专栏,该专栏专注于分享我在YOLOv8目标检测模型中的实战经验,涵盖从入门基础到深度优化的全方位解决方案。无论你是计算机视觉的新手,还是具有多年深度学习经验的专家,本专栏都将为你提供高效、可复现的技术方案,助你掌握YOLOv8的核心技术,提升目标检测性能,突破瓶颈,优化模型,并加速项目开发🚀!

**My Coding Family** 2104

debugfs:Linux 内核调试的利器

debugfs:Linux 内核调试的利器

似霰的博客 1819

通过Power Platform自定义D365 CE 业务需求 - 4. 使用Power Automate

Power Automate构建块Power Automate中的连接器流的类型和用途流中的动态值和表达式使用变量、循环和条件在Power Automate中处理审批业务场景、用例和实现Power Virtual Agent的概念Power Virtual Agent的构建块配置Power Virtual Agent示例在公共网站/门户中部署Power Virtual Agent业务场景、用例和实现。

Martin-Mei的博客 560

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

linux内核里的Debugfs

Linux内核里的DebugFS 2011-01-17 23:52 by wwang, 12517 阅读, 6 评论, 收藏, 编辑 DebugFS,顾名思义,是一种用于内核调试的虚拟文件系统,内核开发者通过debugfs和用户空间交换数据。类似的虚拟文件系统还有procfs和sysfs等,这几种虚拟文件系统都并不实际存储在硬盘上,而是Linux内核运行起来后才建立起来。 通

liushi558 548

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

Linux Debugfs 深度解析:内核调试的利器

n";if (*ppos!// 确保字符串终止return ret;// ... 前面的初始化代码 ...// 创建自定义文件return 0;这个示例展示了如何实现完整的文件操作, 包括读写和定位.和是内核提供的辅助函数, 简化了用户空间和内核空间之间的数据拷贝。

X 645

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

Linux用户与内核空间交互—debugfs

用户空间与内核的交互方式,使用copy_from_user(), copy_to_user().除了这两种交互方式,内核还提供了其他高级的方式,对于写驱动来说很重要。有proc、sysfs、debugfs、netlink、ioctl。本文学习debugfs。

2138

linux 内核 debugfs 使用介绍

debugfs是 Linux 内核提供的一个特殊的虚拟文件系统,用于 暴露内核模块(如驱动)内部的调试信息或控制接口,供开发者、调试人员实时查看和排查问题。即debugfs就是一个“调试专用的 /proc 或 /sys”,方便你在不重启或不修改代码的情况下,查看内核模块的运行状态、统计信息,甚至直接向内核模块传递调试指令。

GPU全栈博主 777
上一篇: Android 7.0 init.rc的一点改变
下一篇: Android recovery支持adb shell
makeyourprogress
博客等级 码龄11年 26粉丝 57原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值