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
- Linux内核开发的一点调试技巧
- linux 内核调试技巧
- linux内核调试技巧--current的应用
- Linux内核调试技巧--current的应用
- 关于调试的一点技巧
- linux内核调试技巧 dump_stack()
- linux内核的一点总结
- Linux 的内核调试
- linux内核调试技巧之一 dump_stack
- linux内核调试技巧之一 dump_stack
- linux内核调试技巧之一 dump_stack
- linux内核调试技巧之一 dump_stack
- linux内核调试技巧一:printk
- linux内核调试技巧二:dump_stack
- linux内核调试技巧三:kallsyms
- linux内核调试技巧四:gdb调试+vmlinux
- 升级内核的一点心得(Linux)
- OOP和Linux内核的一点思考
- 《Windows游戏编程大师技巧》二、Windows编程模型
- 抽象类
- 解析LINUX的passwd文件
- Linux下连接MySQL数据库的操作示例
- C++_继承名字覆盖
- Linux内核开发的一点调试技巧
- 折线分割平面问题
- 优秀,是一种生活态度
- this
- poj_1088
- 初入码农的路
- 介绍CDN原理的一篇比较不错的文章
- linux read() 函数
- 敏捷开发修炼之道