Linux内核开发的一点调试技巧

来源:互联网 发布:淘宝买华为p8 编辑:程序博客网 时间:2024/05/21 08:50

====本文系本站原创,欢迎转载! 转载请注明出处:http://blog.csdn.net/yyplc==== 

Linux下调试方法多样,可以通过以下这些途径:
1. 使用printk函数
使用printk()函数,加入自己的调试信息。加入的信息时可以是log levels,时间信息,文件名,函数名或者代码行号等等。总之添加的信息越多,所能看到的信息就越多。
2. 使用kernel debuger
使用内核调试工具KDB,或者可以是QEMU和gdb等工具
3.分析Oops信息诊断
当内核遇到一些内部的错误时,它会打印出Oops信息。有时从分析这些Oops中就会很快定位到出错的原因。

本文从调试信息输出的角度来说说Linux内核开发时的调试技巧。
定义一个漂亮的宏,使得代码既简洁又高效,可以有事半功倍的作用。
往往我们在代码中使用宏来定义pringk函数,而不是在代码中见到什么就printk什么.
只有一个好的习惯才会导致一个好的效果。

先复习一下C语言宏定义的连接符的作用,下面这段话是从网上摘录的:
”## 连接符号由两个井号组成,其功能是在带参数的宏定义中将两个子串(token)联接起来,从而形成一个新的子串。但它不可以是第一个或者最后一个子串。所谓的子串(token)就是指编译器能够识别的最小语法单元...同时值得注意的是#符是把传递过来的参数当成字符串进行替代。
#define pasrse( i ) printf( "token" #i " = %d", token##i ) 
//同时定义如下的变量
int token1 = 1;
//宏展开为: 
printf("token" "1" "= %d", token1);
则调用parse(1)的打印结果为:
token1=1“ 
以下是内核中使用printk函数时信息输出的八个级别(在linux/kernel.h):
#define    KERN_EMERG       "<0>"    /* system is unusable*/#define    KERN_ALERT        "<1>"    /* action must be taken immediately*/#define    KERN_CRIT            "<2>"    /* critical conditions*/#define    KERN_ERR             "<3>"    /* error conditions*/#define    KERN_WARNING   "<4>"    /* warning conditions*/#define    KERN_NOTICE       "<5>"    /* normal but significant condition */#define    KERN_INFO             "<6>"    /* informational*/#define    KERN_DEBUG        "<7>"    /* debug-level messages*/
在编写代码时可以根据实际情况选择输出级别,一般选KERN_DEBUG级别。
有用的调试信息有
__FUNCTION__   记录函数名
__DATE__             记录编译日期
__LINE__              记录代码所在行数
__FILE__              记录文件名及路径
__TIME__             记录编译时间   
等,这些是编译器在预处理阶段获得的
综合上面,可以按需要printk。
宏定义printk有多种形式,我们可以这样来定义我们的宏:
A形式:
#define dbg(arg...) printk(arg)
这样的做和直接printk没有区别。
B形式:
#define dbg(x) printk("%s",x)
这样可以,不过有时会觉得麻烦。
C形式:
#define dbg(leve,fmt,args...) printk(level,"%d,%s,%c",fmt "\n",var1,var2,var3,##arg)
还是喜欢这样的,简洁灵活。
当取消printk时,一般有两种方式定义一个什么都不干的'东西:
A形式:
#define dbg(...)  do {}  while(0)
B形式:
#define dbg(...)  (void)(0)

上面两种是等价的。


测试代码:

功能:Linux下一个混杂设备驱动的测试(linux-2.6.35.30)

#include <linux/module.h>#include <linux/kernel.h>#include <linux/errno.h>#include <linux/platform_device.h>#include <linux/irqflags.h>#include <linux/slab.h>#include <linux/init.h>#include <linux/idr.h>#include <linux/mutex.h>#include <linux/miscdevice.h>#include <linux/fs.h>#define MY_DEBUG #ifdef MY_DEBUG#define dbg(fmt,arg...) printk(KERN_DEBUG "my_debug:\npath:%s\nfunction:%s(),line:%d,date:%s,time:%s\n" fmt "\n", __FILE__, \                              __FUNCTION__, __LINE__,__DATE__, \             __TIME__, ##arg)#else#define dbg(fmt,arg...)    do {}  while(0)//#define dbg(fmt,arg...)  (void)(0)#endifstatic int my_open(struct inode *inode, struct file *file){dbg("file open ok");return 0;}static ssize_t my_read(struct file *file, char *buf, size_t size, loff_t *pos){dbg("file read ok");return size;}static ssize_t my_write(struct file *file, char *buf, size_t size, loff_t *pos){dbg("file write ok");return size;}static int my_release(struct inode *inode, struct file *file){dbg("file release ok");return 0;                                                                                      }static const struct file_operations my_fops = {.owner     = THIS_MODULE,.open    = my_open,.read    = my_read,.write   = my_write,.release = my_release,};struct miscdevice my_misc_dev = {.minor = MISC_DYNAMIC_MINOR,.name  = "my_dev",.fops  = &my_fops,};static int __init my_dev_init(void){int res;res = misc_register(&my_misc_dev);if (res) {dbg("misc_register error: %d",res);return res;}dbg("mis_register ok");return res;}static void __exit my_dev_exit(void){misc_deregister(&my_misc_dev);dbg("mis deregister ok");return;}module_init(my_dev_init);module_exit(my_dev_exit);MODULE_AUTHOR("itspy.wei<itspy.wei@gmail.con>");MODULE_DESCRIPTION("linux debug using printk");MODULE_LICENSE("GPL");
Ubuntu上测试结果:
[15449.892067] mis_register ok[16050.131267] my_debug:[16050.131269] path:/home/wsn/my_module/my_debug/my_debug.c[16050.131270] function:my_open(),line:28,date:Apr 15 2012,time:16:02:10[16050.131272] file open ok[16050.131304] my_debug:[16050.131305] path:/home/wsn/my_module/my_debug/my_debug.c[16050.131306] function:my_write(),line:44,date:Apr 15 2012,time:16:02:10[16050.131307] file write ok[16050.131336] my_debug:[16050.131337] path:/home/wsn/my_module/my_debug/my_debug.c[16050.131338] function:my_read(),line:37,date:Apr 15 2012,time:16:02:10[16050.131339] file read ok[16050.131349] my_debug:[16050.131350] path:/home/wsn/my_module/my_debug/my_debug.c[16050.131351] function:my_release(),line:52,date:Apr 15 2012,time:16:02:10[16050.131352] file release ok

原创粉丝点击