Linux驱动设计—— 驱动调试技术
参考博客与书籍:
《Linux设备驱动开发详解》
《Linux设备驱动程序》
http://blog.chinaunix.net/uid-24219701-id-2884942.html
对于驱动程序设计来说,核心问题之一就是如何完成调试。当前常用的驱动调试技术可分为:
1. 打印调试
printk
重定向控制台消息
消息记录
开启和关闭消息速度限制
打印设备编号
2. 调试器调试
gdb
kdb内核调试器
kgdb补丁
3. 查询调试
使用/proc文件系统
ioctl方法
4. 监视调试
oops消息
5. 工具包
动态探测(DProbes,一种调试工具)
Linux跟踪工具包
打印调试 (类似编写应用程序时常用条件编译的Debug宏)
细节参考http://blog.csdn.net/flowingflying/article/details/4534120
在驱动开发时,printk 非常有助于调试。但当正式发行驱动程序时, 应当去掉这些打印语句。但你有可能很快又发现,你又需要在驱动程序中实现一个新功能(或者修复一个bug),这时你又要用到那些被删除的打印语句。这里介绍一种使用printk 的合理方法,可以全局地打开或关闭它们,而不是简单地删除。
#ifdef PDEBUG
#define PLOG(fmt,args...) printk(KERN_DEBUG"scull:"fmt,##args)
#else
#define PLOG(fmt,args...) /*do nothing */
#endif
Makefile作如下修改:
DEBUG =y
ifeq ($(DEBUG),y)
DEBFLAGS =-O2 -g -DPDEBUG
else
DEBFLAGS =-O2
endif
CFLAGS +=$(DEBFLAGS)
实例:
/*
* 输出调试信息
* Lzy 2011-9-26
*/
#include <linux/init.h>
#include <linux/module.h>
#define DEBUG_SWITCH 1 /*1:输出 0:不输出*/ #if DEBUG_SWITCH
#define P_DEBUG(fmt,args...) printk("<kernel>:[%s]<Function> [%d]Line: "fmt, __FUNCTION__, __LINE__, ##args)
#else
#define P_DEBUG(fmt,args...) /*do nothing */
#endif static int hello_init(void)
{
char *name = "Lzy";
P_DEBUG( "Hello %s\n",name); /* 打印hello World */
return 0;
} static void hello_exit(void)
{
P_DEBUG( "Goodbye, world\n"); /* 打印Goodbye,world */
} module_init(hello_init); /* 指定模块加载函数 */
module_exit(hello_exit); /* 指定模块卸载函数 */ MODULE_LICENSE("GPL");
调试工具: GDB ,KDB,KGDB
都需要编译DEBUG版本内核。
KDB单机汇编级调试,需要单独下载kernel对应的patch,
GDB没整明白,只知道 gdb vmlinux启动后 通过add-symobl-file增加被调试模块的符号信息
KGDB 在2.6.*后就已缺省放在内核源码里了,其他的需要单独下载PATCH,反正我的2.6.18内核里没有(在kernel.org中,people/ark 下应该能找到2.6.18的patch,注意打patch的顺序)
查看是否有KGDB的方法是:源码路径下make menuconfig后能看到KGDB这一项。下面主要介绍2.6.18上KGDB环境的建立:
KGDB需要两台机器配合,一个开发机,一个测试机,两台机器通过串口线连接(该线是需要处理的,具体的与window上调试驱地的一致)
a.硬件连接性测试:在开发机上 执行 stty -ispeed 115200 -ospeed 115200 -F /dev/ttyS0
在测试机上 执行 stty -ispeed 115200 -ospeed 115200 -F /dev/ttyS0
在开发机上 执行 cat /dev/ttyS0
在测试机上 执行 echo "12345" < /dev/ttyS0
如果在开发机上能看到 12345表示两台机器连通
b.内核编译:在开发机上准备好内核源码及对应的KGDB patch文件(我使用的2.6.18-92.el5)
make menuconfig 选上KGDB
make modules
make modules_install (把编译后的模块文件安装到当前系统的 /lib/moudles/××××下)
在源码文件存放的一级目录下生成System.map文件,在arch/i386/boot下生成bzImage,把这两个文件拷贝到/boot下并重命名:
cp System.map /boot/System.map-2.6.18-92
cp bzImage /boot/vmlinuz-2.6.18-92
创建 连接: ln -s System.map-2.6.18-92 System.map
ln -s vmlinuz-2.6.18-92 vmlinuz
制作initrd 文件:mkinitrd initrd-2.6.18-92 ****(****表示make modules_install时在/lib/modules下新创建的文件夹名)
c. 启动新编译内核
打开/boot/grub/grub.conf,这个文件就像XP里的boot.ini一样,拷贝一份
将对应的vmlinuz... 和 initrd...改成上面步骤中准备好的 ,同时需要增加启动参数:
kgbwait kgdb8250=0,115200 (应该本试验中使用的KGDB patch中支持8250)
这样修改后启动会进入等连接的状态,一般在开发机上,可以先不加kgdbwait kgdb8250....这个参数,从而让系统直接启动起来,这样可以判断新编译的内核是否正确。
d.布置测试机
在上步能够确保启动新内核后,将vmlinuz-2.6.18-92和initrd-26.18-92两个件弄到测试机上,并修改启动项以KGDB方式启动
e.开始内核调试(注意内核调试与内核模块调试不是一个概念)
在开发机上,源码路径下执行gdb ./vmlinux 进入GDB
执行 set remotebaud 115200
target remote /dev/ttyS0
如果成功后看到断点停在kgdb.c中 ,表示此时已经连接到测试器上
输入 c 让测试机继续启动,可以随时按ctrl+c 停步测试器
在ctrl+c 停止测试器后,便可在相要的地方增加断点,进行内核单步查看调试
f.如果要是调试内核模块 例如某驱动模块 test.ko 需要在开发机上使用gdbmod来代替gdb工具
gdbmod ./vmlinux 启动调试器后与gdb操作相同
关键在于如何加裁被调试驱动模块的符号文件(没尝试成功,因为我想调试init函数,此时驱动还没加裁)
网上搜到的是在开发机的gdbmod下使用,set s.....path 来增加符号文件路径,这样在测试机上执行insmod test.ko后 在开发机上的gdbmod就能够找到test.ko的符号文件,可是我没尝试成功,以后还要再试
To be continue... (在后续的学习中不断完善)
Linux驱动设计—— 驱动调试技术的更多相关文章
- Linux下的反调试技术
Linux下的反调试技术 2014年01月30日 ⁄ 综合 ⁄ 共 2669字 ⁄ 字号 小 中 大 ⁄ 评论关闭 转自 http://wangcong.org/blog/archives/310 ...
- 嵌入式Linux系统Bootloader启动调试技术(回想)
嵌入式系统搭建过程中,对于系统平台搭建project师最初的一步一般是移植Bootloader ,当然移植有几个级别,通常最常见的是參考的EVM 的硬件有了改动(如更改了FLASH ,更改了SDRAM ...
- linux后端诊断与调试技术
本文不是liunx命令使用教程,也不打算全方面阐明其用法,互联网公司项目很多,服务程序之间相互依赖调用很复杂,各种因素会影响线程服务正常运行,特别是基础服务组件更是如此,当出现各种问题时,如何诊断li ...
- 领域驱动设计理解&总结
领域驱动设计理解&总结 这篇文章主要是通读<实现领域驱动设计>之后自己的理解和总结(同时也参照一些博文的分析来加深自己的理解): 有些疑问是自定义内容,虽然有自己的理解,但依然感觉 ...
- linux内核调试技术之printk
原创博客:欢迎转载,转载请注明出处https://i.cnblogs.com/EditPosts.aspx?postid=6218383 1.简介(基于s3c2440 linux) 在内核调试技术之中 ...
- 第十章 嵌入式Linux的调试技术
对调试工具进行简介.Linux中提供了一类工具,通过这些工具可以逐行跟踪程序的代码,用于测试用户空间程序的gdb.gdbserver和调试内核空间程序的kgdb. 用gdb调试用户空间程序:gdb可跟 ...
- 【转】Linux Shell脚本调试技术
本文转载自:https://www.ibm.com/developerworks/cn/linux/l-cn-shell-debug/ Shell脚本调试技术 本文全面系统地介绍了shell脚本调试技 ...
- Linux驱动设计—— 中断与时钟
中断和时钟技术可以提升驱动程序的效率 中断 中断在Linux中的实现 通常情况下,一个驱动程序只需要申请中断,并添加中断处理函数就可以了,中断的到达和中断函数的调用都是内核实现框架完成的.所以程序员只 ...
- Linux用户态驱动设计
聊聊Linux用户态驱动设计 序言 设备驱动可以运行在内核态,也可以运行在用户态,用户态驱动的利弊网上有很多的讨论,而且有些还上升到政治性上,这里不再多做讨论.不管用户态驱动还是内核态驱动,他们都 ...
随机推荐
- jquery api调用
本框架内置组件以及部分插件都可以通过jquery选择器进行API调用,支持链式操作,如下示例. <script type="text/javascript"> $(&q ...
- MapReduce数据流(二)
输入块(InputSplit):一个输入块描述了构成MapReduce程序中单个map任务的一个单元.把一个MapReduce程序应用到一个数据集上,即是指一个作业,会由几个(也可能几百个)任务组成. ...
- android平台手电筒开发源代码
android平台手电筒开发源代码,AndroidManifest.xml文件的入口是startapp,这个文件没上传上来,大家可以自己写. 1. [代码]android 1 2 3 4 5 6 7 ...
- IOS 设置透明度导致底层View始终可见
正确效果如图:下面的toolBar应该看不见它下面的View, 避免方法:[self.view addSubView:aSubView];这个aSubView一定不能设置不透明度,应将其设置为Cle ...
- [UIImage resizableImageWithCapInsets:]使用注意
转自:http://www.cnblogs.com/scorpiozj/p/3302270.html 最近在sae上搭建了个wp,因为深感自己前端的东西缺乏,所以想依次为契机,学习一下.本文是从个人的 ...
- UITouch的用法
UITouch一般无法直接获取,是通过UIView的touchesBegan等函数获得. //这四个方法是UIResponder中得方法 // Generally, all responders wh ...
- STL 源码分析《2》----nth_element() 使用与源码分析
Select 问题: 在一个无序的数组中 找到第 n 大的元素. 思路 1: 排序,O(NlgN) 思路 2: 利用快排的 RandomizedPartition(), 平均复杂度是 O(N) 思路 ...
- JS判断移动设备最佳方法 并实现跳转至手机版网页
我在开发的Magento或Wordpress主题时,通过都会制作手机版本,为了实现某个片段在手机端和桌面端不同功能,又或者如果是手机设备,就跳转到指定的网页上,那么这里就需要用到JS来做判断了,下面有 ...
- Linux基础入门(新版)(实验五至实验八)
实验五 环境变量与文件查找 (环境变量的作用与用法,及几种搜索文件的方法) 一.环境变量 1.变量 (1)常变量与值是一对一的关系 (2)变量的作用域即变量的有效范围(比如一个函数中.一个源文 ...
- Qt Clipboard剪贴板简单使用
设置剪贴板的内容 QClipboard *clipboard = QApplication::clipboard(); clipboard->setText("contents&quo ...