打印
[嵌入式linux]

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

[复制链接]
1926|2
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
yyplc|  楼主 | 2012-4-15 18:00 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 yyplc 于 2012-4-16 09:52 编辑

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)

http://blog.csdn.net/yyplc/article/details/7460730

测试结果:




  • [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










相关帖子

沙发
青山电子| | 2012-5-12 08:34 | 只看该作者
好**,学习了

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

15

主题

262

帖子

1

粉丝