转载地址:
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):
[cpp] view plaincopy
#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)
阅读(2070) | 评论(0) | 转发(0) |