Linux之debugfs介绍

来源:互联网 发布:hbuilder for mac下载 编辑:程序博客网 时间:2024/04/20 11:52

Linuxdebugfs介绍

Debugfs是一种用于内核调试的虚拟文件系统,在内核源码中经常可以看到它的使用,今天我来大概介绍一下它的使用。

如果你对debugfs不熟悉,那么也许你会对sysfs比较熟悉,对于调试方面,其实两个文件系统还是挺类似的,但是sysfs的引入内核主要是用于驱动模型的。所以我们在平时调试的时候应该尽量避免使用sysfs,而使用debugfs

好了,下面我们来介绍一些debugfs的使用,要使用debugfs首先我们要设置一下配置选项CONFIG_DEBUG_FS,可以在config文件中设置CONFIG_DEBUG_FS=y,也可以通过menuconfig来设置,如图:

[html] view plaincopy
  1. Kernelhacking --->  
  2.   
  3.             [*]Debug Filesystem  

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

使用如下命令:

[html] view plaincopy
  1. <span xmlns="http://www.w3.org/1999/xhtml" style="">mount-t debugfs none /mnt</span>  

然后进入/mnt后就可以看到我们在系统中创建的这些文件。

下面我们开始说一下如何在驱动中使用debugfs.

首先我们需要创建一个自己的目录,利用如下函数:

[html] view plaincopy
  1. <span xmlns="http://www.w3.org/1999/xhtml" style="">struct dentry *debugfs_create_dir(const char *name, struct dentry *parent);</span>  

name就是创建的目录的名字,parent是该目录的父目录,如果是NULL的话,则所创建的目录就在debugfs的根目录,具体使用如下:

[html] view plaincopy
  1. static struct dentry *binder_debugfs_dir_entry_root;  
  2. binder_debugfs_dir_entry_rootdebugfs_create_dir("binder", NULL);  

这样就会在debugfs的根目录下创建一个binder的目录,有了目录还需要有可供读写的文件吧,下边就是另一个重要的函数,文件的创建:

[html] view plaincopy
  1. struct dentry *debugfs_create_file(const char *name, mode_t mode,  
  2. struct dentry *parent, void *data,  
  3. const struct file_operations *fops)  

如其函数名,这个函数的作用就是在parent这个目录下创建一个名为name的文件,mode是这个文件读写权限,data是传入的参数,fops就比较重要了,为我们的文件提供实际的读写操作。

binder驱动中创建了如下文件

[html] view plaincopy
  1. debugfs_create_file("state",  
  2. S_IRUGO,  
  3. binder_debugfs_dir_entry_root,  
  4. NULL,  
  5. &binder_state_fops);  
  6.   
  7. debugfs_create_file("stats",  
  8. S_IRUGO,  
  9. binder_debugfs_dir_entry_root,  
  10. NULL,  
  11. &binder_stats_fops);  
  12.   
  13. debugfs_create_file("transactions",  
  14. S_IRUGO,  
  15. binder_debugfs_dir_entry_root,  
  16. NULL,  
  17. &binder_transactions_fops);  
  18.   
  19. debugfs_create_file("transaction_log",  
  20. S_IRUGO,  
  21. binder_debugfs_dir_entry_root,  
  22. &binder_transaction_log,  
  23. &binder_transaction_log_fops);  
  24.   
  25. debugfs_create_file("failed_transaction_log",  
  26. S_IRUGO,  
  27. binder_debugfs_dir_entry_root,  
  28. &binder_transaction_log_failed,  
  29. &binder_transaction_log_fops);  

如上图所示,在binder目录下创建了proc/state/stats/transactions/transaction_log/failed_transaction_log这些文件。

binder中这些文件的fops全部用一个宏来完成了

[html] view plaincopy
  1. #define BINDER_DEBUG_ENTRY(name) \  
  2. static int binder_##name##_open(struct inode *inode, struct file *file) \  
  3. {\  
  4. return single_open(file, binder_##name##_show, inode->i_private); \  
  5. }\  
  6. \  
  7. static const struct file_operations binder_##name##_fops = { \  
  8. .ownerTHIS_MODULE, \  
  9. .openbinder_##name##_open, \  
  10. .readseq_read, \  
  11. .llseekseq_lseek, \  
  12. .releasesingle_release, \  
  13. }  

可以看到binder没有实现write操作。read则全部使用seq_file的操作,seq_file2.4.15以后版本的内核中出现的新功能,使得内核输出大文件信息。这边我们就不去将seq了,我们放在另外的一篇文章里面去讲。

debugfs除了实现这个文件对函数的功能,还提供了一些API用来针对变量的操作:

[html] view plaincopy
  1. struct dentry *debugfs_create_u8(const char *name, mode_t mode, struct dentry *parent, u8 *value);  
  2. struct dentry *debugfs_create_u16(const char *name, mode_t mode, structdentry *parent, u16 *value);  
  3. struct dentry *debugfs_create_u32(const char *name, mode_t mode, structdentry *parent, u32 *value);  
  4. struct dentry *debugfs_create_bool(const char *name, mode_t mode, structdentry *parent, u32 *value);  

这样就可以在用户态去调试内核变量value了。

当内核卸载时,debugfs并不会自动的去清除我们创建的这些文件,对于创建的每一个文件我们都需要调用如下函数接口去清除:

0 0