现在流行的开源项目经历了长时间的开发, 积累了大量的代码, 想要一行一行地阅读代码去学习开源项目, 需要的时间成本是巨大的. 所以, 我们也需要用一种高效的方式去"阅读"代码. 计算机科学发展到现在, 产生了很多高效成熟的工具, 调试器就是其中之一(扯句题外话, 那些大牛程序员似乎就是喜欢琢磨怎么制造各种工具哈), 调试器能够帮程序员定位代码的bug, 理解代码的运行机制. 这篇文章总结了如何搭建一个调试linux内核源码的开发环境, 并简单介绍了一些调试器的实现原理.
调试内核和调试用户态程序有什么区别?
使用qemu调试内核, 原理是什么?
如何搭建调试linux内核源码的开发环境?
我们把讨论限定在使用c语言写的程序上, 一个程序想在linux运行, 大致会经过下面几个步骤:
以上是用户态进程的运行过程, 如果想调试一个用户态程序, 可以使用gdb工具, gdb之所以能够调试程序, 是借助了内核的帮助. 如果理解了进程是一个状态机这样的观点, 理解gdb调试程序的原理就比较容易了, 调试程序无非就是运行几条指令,观察或者修改一下内存和寄存器的状态. 内核提供了ptrace系统调用, 可以让一个进程去"跟踪(trace)"另一个进程的状态, 使用ptrace系统调用, gdb可以修改被调试进程的内存和寄存器, 比如修改原来内存中的某条指令为另一条特殊的指令, 就可以实现"打断点"的功能, 具体的细节会在其他文章中讨论, 手写一个简单的调试器体会一下ptrace系统调用.
调试用户态程序依赖内核提供的系统调用, 但是调试内核本身, 就不能再依赖它本身提供的系统调用了, 我们需要一种仿真器软件, 也就是接下来要介绍的qemu.
qemu是一种仿真器软件, 用软件的方式模拟了一整个硬件平台, 支持不同类型的CPU架构, 众多的IO设备. 使用qmeu, 可以运行完整的linux操作系统, 通过qemu的启动参数可以方便地添加修改硬件的配置, 比如CPU的数量, 增加硬盘, 网卡等设备. 对于调试内核来说, 我们需要把编译好的内核镜像传递给它, 依赖qemu提供的gdb调试服务支持, 改变启动参数, 可以让qemu启动内核的同时启动一个gdb server服务, 在特定的端口上等待gdb client的连接, 并执行gdb client的命令.
以上就是使用qemu调试内核的基本原理. 从操作系统的角度看, qemu也是一个普通的用户进程, 只不过它可以仿真一台真实的机器, 并且能够接受另外的gdb client进程的命令, 从而控制其中运行的linux内核的执行. 这个gdb client进程既可以和qemu在统一台机器上运行, 也可以通过网络连接到qemu的gdb server服务, 使用起来比较方便.
以下均在ubuntu系统上完成, 需要准备的内容包括:
交叉编译工具链
linux内核源码
busybox源码
安装好的qemu
其他软件
具体的调试环境准备可以参考下面的视频:
按照视频的步骤操作下来, 实现调试linux内核应该不会有什么问题. 但是qemu的一些启动参数, 传递给内核的启动参数, 以及这些参数为什么要这样设置, 是否可以改成其他的值, 可能还是会有疑惑的. 我的建议是, 先把环境搞起来, 等对qemu和内核源码熟悉一点了, 很多问题自然就明白了.
总而言之, 源码之下没有秘密. 读文档, 读源码能够解决你的大部分问题.
建了个QQ群: 838923389. 有想法的老铁可以加一下, 一起交流linux内核的使用和学习经验. 后续也会在b站发一些技术视频, 老铁们觉得有需要可以先关注一下, 视频和文章肯定会给各位带来一些启发和帮助. 更多文章还可以参考我的csdn.
手机扫一扫
移动阅读更方便
你可能感兴趣的文章