嵌入式Linux内核调试技术
模块内核的调试
我们使用BDI2000来调试Linux内核的另外一个重要原因,就是它可以支持调试内核模块。内核模块是一些可以让操作系统内核在需要时载入和执行的代码,这意味着它可以在不需要时由操作系统卸载。这种方式可以扩展操作系统内核的功能,而不需要重新启动系统,这一点对调试驱动程序的工程师特别有用。因为如果驱动程序编译进内核的话,会增加内核的大小,还要改动内核的源文件,而且不能动态的卸载,不利于调试,所以推荐使用模块方式。
调试Linux 2.4内核模块
Linux 2.4内核模块的调试比较简单,使用命令"insmod -m"来加载模块。参数"-m"非常重要,它的功能是在把模块加载到内存时产生一个加载map表。然后通过LinuxScope调试器加载相应的调试信息。例如:
[root@lisl tmp]# insmod -m hello.o >modaddr
查看模块的加载信息文件modaddr如下:
.this 00000060 c88d8000 2**2
.text 00000035 c88d8060 2**2
.rodata 00000069 c88d80a0 2**5
……
.data 00000000 c88d833c 2**2
.bss 00000000 c88d833c 2**2
……
在这些信息中,我们用到的只有.text、.rodata、.data、.bss。当然,把相关的信息输入LinuxScope调试器,它会把以上地址信息加入到gdb中进行模块功能的调试。
这里需要注意的是对模块进行编译时,也需要增加"-g"选项。
另外,这种方法也存在一定的不足,它不能调试模块初始化的代码,因为此时模块初始化代码已经执行过了。如果初始化部分有问题,那么将无法进行调试。遇到这样的情况可以修改代码,延迟初始化部分的执行。另外,也可以采用以下替代方法:当插入内核模块时,内核模块机制将调用函数sys_init_module (kernel/modle.c)执行对内核模块的初始化。程序代码片断如下:
……
if (mod->init != NULL)
ret = mod->init();
……
在该语句上设置断点,也能在执行模块初始化之前停下来。
调试Linux 2.6内核模块
在Linux 2.6内核系统中,由于module-init-tools工具的更改,insmod命令不再支持-m参数,只有采取其他的方法来获取模块加载到内核的地址。
比较简单的方式是修改内核配置文件,使系统支持CONFIG_KALLSYMS,这样就可以把相关的符号信息放到目录/sys下,然后通过LinuxScope调试器加载相应的调试信息。通过在模块初始化函数中放置一下代码,也可以获得模块加载到内存中的地址,只是这样要麻烦一些。
应用程序的调试
到了应用程序调试的阶段,仿真器就可以"功成身退"了,剩下的调试任务就由LinuxScope调试器来独自完成。此时只要在目标系统中启动"gdbserver",调试应用程序非常的方便。
结语
面向行业、应用和设备的嵌入式Linux工具软件和嵌入式Linux操作系统平台是未来发展的必然趋势。跟踪Linux的发展,符合标准,遵循开放是大势所趋,嵌入式Linux也不例外。Linux调试技术的进步为Linux在嵌入式领域的应用广泛性提供了保证。本文所讲述的仿真器技术和调试器技术可以极大的提高开发者的效率。
- Linux嵌入式系统开发平台选型探讨(11-09)
- 基于Winodws CE的嵌入式网络监控系统的设计与实现(03-05)
- 嵌入式系统实时性的问题(06-21)
- 嵌入式实时系统中的优先级反转问题(06-10)
- 嵌入式Linux系统中MMC卡驱动管理技术研究(06-10)
- FPGA的DSP性能揭秘(06-16)