驱动篇:设备驱动的调试(三)(摘录)
发布日期:2021-06-29 11:35:01 浏览次数:2 分类:技术文章

本文共 2174 字,大约阅读时间需要 7 分钟。

驱动篇:设备驱动的调试(三)(摘录)

监视工具

在 Linux 系统中,strace 是一种相当有效的跟踪工具,它的主要特点是可以被用来监视系统调用。我们不仅可以用 strace 调试一个新开始的程序,也可以调试一个已经在运行的程序(这意味着把 strace 绑定到一个已有的 PID 上) 。对于第 6 章的globalmem 字符设备文件,以 strace 方式运行如代码清单 22.9 所示的用户空间应用程序 globalmem_test
在这里插入图片描述输出的每一行对应一次 Linux 系统调用,其格式为“左边=右边”,等号左边是系统调用的函数名及其参数,右边是该调用的返回值

使用 strace 虽然无法直接追踪到设备驱动中的函数,但是足够可以帮助工程师推演,如从“open("/dev/globalmem", O_RDWR) = 3”的返回结果知道/dev/globalmem 的fd 为 3,之后对 fd 为 3 的文件进行的 read()、write()和 ioctl()系统调用最终都会引起globalmem 中 file_operations 中的相应函数被调用, 通过系统调用的结果就可以知道驱动中 globalmem_read()、globalmem_write()和globalmem_ioctl()的运行结果。

内核调试器

kcore
GDB 调试器可以把内核作为一个应用程序来调试,在这种方式中,需要给 GDB指定未压缩的内核映像的文件名和“core 文件”的名字。对于一个正在运行的内核,“core 文件”就是运行时的内存映像/proc/kcore(kcore 代表整个内核地址空间,对应于所有的物理内存)。因此,使用 GDB 和 kcore 调试内核的典型命令如下:

gdb /usr/src/linux/vmlinux /proc/kcore

第一个参数是非压缩的 ELF 核心可执行文件的名字,不能是 zImage、bzImage。第二个参数是内核档案的名称,如同其他/proc 中的文件,/proc/kcore 是在被读的时候才产生的。

在“gdb

/vmlinux /proc/kcore”这种调试方式中,可用 print 命令打印变量,如“print jiffies”。当从 GDB 打印数据时间,GDB 会缓存已经读取的数据,但是由于内核正在执行,各种数据项在不同时间有不同的值,GDB 的缓存可能导致连续多次读取同一变量得到相同的值。例如,多次显示 jiffies:

(gdb) print jiffies$3 = 153729(gdb) print jiffies$4 = 153729(gdb) print jiffies$5 = 153729

虽然 jiffies 已经变更了,但每次 print 出来的都是第 1 次的值 153729。为避免此问题,我们可以在需要刷新 GDB 缓存时发出“core-file /proc/kcore”命令,这将导致调试器使用新的“core 文件”并且丢弃旧信息。当执行“core-file /proc/kcore”命令后,再运行“print jiffies”,值会发生变化,如下所示:

(gdb) core-file /proc/kcoreCore was generated by 'ro root=/dev/sda1 hdc=ide-scsi'.#0 0x00000000 in globalmem_fops ()(gdb) print jiffies$6 = 178683

$6 比$3、$4、$5 要大,这说明新的值被 print 出来了。

为了使 Linux 系统中包含/proc/kcore 文件,必须在编译时包含“/proc/kcore support”(如图 22.10 所示),而为了给 GDB 提供 symbol 信息,必须设定 CONFIG_DEBUG_INFO选项来编译内核(如图 22.11 所示)。

在“gdb

/vmlinux /proc/kcore”这种调试方式中,GDB 的绝大多数功能都不能使用,如修改内核变量的值、设置断点、单步执行等,而 22.9.2 和 22.9.3 小节将要介绍的 KDB 和 KGDB 方式则可支持这些功能。

在这里插入图片描述值得一提的是,可加载模块的 symbol 并未包含在 vmlinux 中,必须使用一些辅助方法才能调试模块。 Linux 可加载模块是 ELF 格式的可执行映像, 它们被分成几个段,有 3 个典型的与模块调试相关的段。

l.text:这个段包含模块的可执行程序代码。

l.bss/.data:这两个段包含模块的变量,在编译时未初始化的变量在.bss 中,
而被初始化过的变量在.data 段里。
当一个模块被加载后,/sys/module/目录下会新增一个对应于该模块的目录,如“insmod globalmem.ko” 后, 将生成/sys/module/globalmem, 在该目录下又包含一个 sections目录,运行“ls –a”命令可以获得该目录下包含的文件
在这里插入图片描述在这里插入图片描述之后就可以借用 GDB 的 add-symbol-file 来添加模块的符号信息,这样之后便可以查看模块中的变量了,如下所示:
在这里插入图片描述

转载地址:https://blog.csdn.net/zytgg123456/article/details/110234754 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:驱动篇:设备驱动的调试(四)(摘录)
下一篇:驱动篇:设备驱动的调试(二)(摘录)

发表评论

最新留言

第一次来,支持一个
[***.219.124.196]2024年04月22日 07时20分06秒