Kgdb虚拟机串口调试linux kernel
声明:
1.本文章在注明引用出处的前提下可以随意引用。
2.因为环境有差异,不能保证在您的机器上可以得到同样的结果。
最近在深入探究Linux模块的调试技术。通过研读相关文献了解了这一领域的发展。最终选择了kgdb作为其调试工具。搭建了主机间的互连架构。其中一台运行debug内核用于定位问题。另一台运行测试系统用于验证修正。
运行环境:
- 1.vmware虚拟机7.1.3Linux版
- 主机:redhat企业级Linux6服务器版
- 客户端:
- A. 开发机器:redhat企业级Linux6服务器版
- B. 目标机器:redhat企业级Linux6服务器版
- 4.内核编译版本:2.6.32
配置过程:
-
- 虚拟机安装相对而言比较简单,在root用户的账户下执行./ 即可完成操作。
-
- 安装完成后即可进行redhat系统的安装。这项操作既快速又简便地进行,然而,由于仅为/boot目录分配了47MB的空间限制,因此在编译内核时可能会遇到空间不足的问题,此时建议删除/boot目录下的initrd和initram等关键文件,以便释放出额外的空间以完成必要的配置。
-
- 由于vmware会自动生成虚拟机环境,默认情况下并未安装gdb工具这一重要软件包。对于喜欢构建虚拟化环境的人来说,在Linux环境下确实非常便利。我们可以建立一个本地化的yum升级源,并将其通过共享文件夹或nfs网络存储设备的方式分发给其他机器,从而节省存储空间的同时也能提高工作效率。为了实现这一目标,我选择使用host机器上的现有yum源来进行gdb工具的安装,这样不仅简单而且后续还可以方便地添加其他常用软件包。
-
- 完成基本系统的搭建后即可着手进行内核的编译工作。首先下载2.6.32版本内核源码包(推荐),因为其配置文件位于系统/boot目录下的config文件夹中(版本号相同的情况下发生异常的可能性较低)。整个编译过程相对简单直接:
- 下载并解压内核源码
- 配置必要的参数设置
- 进行make命令启动
- 确保所有日志信息已记录完毕
A.make menuconfig
B.make && make module && make module_install
在配置.config文件的过程中尤其重要。需要注意的是,在make menuconfig的过程中,默认安装时会缺少一些必要的库。menuconfig无法运行。可以通过yum命令安装缺失的库来解决这个问题。
在配置过程中需确保
CONFIG_KGDB=y
CONFIG_KGDB Serial_CONSOLE=y
CONFIG_MAGIC_SYSRQ=y
CONFIG_DEBUG_INFO=y
此外必须确保CONFIG_DEBUG_RODATA不被选上
建议最好是在make menuconfig中进行配置以避免遗漏相关设置
还有人认为应该关闭Makefile中的O2优化开关这一设置。虽然这看起来似乎是合理的建议,但年轻的技术人员往往缺乏这样的操作技能。如果不关闭这一开关,在内核进行编译时可能会出现一些问题。因为如果不关闭这个选项,在内核编译时可能会出现一些问题。这是因为内核内部存在一些函数只有在开启O2优化开关时才能正常运行。如果你希望取消这种优化功能,则需要先修改内核代码以适应相应的要求。目前我没有这种能力。
接下来是B部分的一些命令。可以通过&&执行命令之间的逻辑与操作,并根据具体情况灵活运用它们之间的关系进行处理。比如我想了解为何没有将make install一并包含进来?因为我觉得通过使用clone方法可以更方便地进行调试和查看代码,在编译过程中也需要访问源代码目录,并且对于在另一台机器复制相同目录结构来说是必要的;也就是说,在另一台机器上复制相同的目录结构到相应位置是必须的;你可以确认安装完成后位于lib/modules/$(shell uname -r)/bulid目录以及source目录的具体位置;这些信息都与编译过程相关联
-
- 完成之后就可以复制一个同样的虚拟主机了。复制后就需要安装内核了。此时可以直接清除/删除 /boot文件夹下的目录中的原有的内核文件。我们知道这些文件都是长驻内存中的,在整个系统启动(boot)到关闭(shutdown)的过程中即使删除这些文件也不会影响系统的正常运行。完成上述操作后即可执行编译命令make install。
-
6.完成编译后,就需要检查新内核是否能够正常运行.尝试重启系统,观察结果.如果能够正常运行,那么就可以开始庆祝啦.
-
7.这时候就可以配置串口参数.在虚拟机环境中设置串口配置非常简便.
实际上是为vmware配置一个 named 管道。具体操作是:在虚拟机上启动配置界面,在"设备"栏目中选择新增串口(Note: 在vmware中直接出现的是串口2号),但这个串口对应的 /dev 目录下的 ttyS1 已经被分配给打印机了(Note: 在Linux中是从0-3号分配给ty),而vmware是从1-4号分配的,请自行区分清楚后再操作。接下来只需选择 socket 接口,在其下方输入文件名即可完成配置(Note: 建议使用/tmp/serial_socket 这个路径)。一旦启动就会生成该 socket 文件(Note: 可通过 file 命令查看其内容),方便后续操作。
串口配置过程中需要注意的是,在设置串口时需要考虑从客户端到虚拟机以及从服务器到虚拟机的方向(Note: 这两点之间没有强制限制)。两个虚拟机各自分配一个方向即可满足需求(Note: 不需要互相影响)。完成配置后就可以进行测试了:将两个主机都切换至 root 模式,并按照以下命令设置串口速率:
stty ispeed 115200 ospeed 115200 -F /dev/ttyS1
其中/ttyS* 应与对应的虚拟机串口号保持一致(Note: 这里需要注意缓存机制的存在可能导致的现象)。设置完成后可以通过以下测试来验证数据传输功能:
A主机执行 cat /dev/ttyS1
B主机执行 echo "hello world" > /dev/ttyS1如果A主机能够成功显示 echo 输出的内容,则表示配置成功!需要注意的是:必须先等待数据流入后再执行 echo 命令(Note: 否则可能会因为缓存导致无法看到输出结果)。
-
- 如果你能够走到现在这一步,则意味着你已经取得了一定的成功。\n我们现在可以直接更改/boot/grub/grub.conf文件。\n在你自己编译内核的地方就是那个kernel /boot/vmlinuz-----------------\n的最后加上ro kgdb=ttyS1,115200 kgdboc=ttyS1,115200 kgdbwait的话,则表示kgdb和kgdboc都需要有。\n并且在ttyS1,115200之间不能有任何空格出现,请自行妥善安排。\n然后我们就可以把这个拥有自己编译内核的主机进行重启。\n通常会立即显示类似kgdb:等待远程gdb之类的提示信息。\n到另一台主机上切换到root模式后,在编译内核的位置执行以下操作:\ngdb vmlinuz即可启动gdb进行调试。\n首先需要加载vmliunz符号(虽然因为有info的缘故文件较大),\n之后则会进入gdb等待输入的状态。\n要与远程主机建立连接(尽管这只是一台虚拟机),可以通过以下命令设置:
set remotebaude 115200 target remote /dev/ttyS1.\n一旦连接建立成功即可观察到相关的调试信息(即断点)。\ngdb将一直等待用户的输入。
- 如果你能够走到现在这一步,则意味着你已经取得了一定的成功。\n我们现在可以直接更改/boot/grub/grub.conf文件。\n在你自己编译内核的地方就是那个kernel /boot/vmlinuz-----------------\n的最后加上ro kgdb=ttyS1,115200 kgdboc=ttyS1,115200 kgdbwait的话,则表示kgdb和kgdboc都需要有。\n并且在ttyS1,115200之间不能有任何空格出现,请自行妥善安排。\n然后我们就可以把这个拥有自己编译内核的主机进行重启。\n通常会立即显示类似kgdb:等待远程gdb之类的提示信息。\n到另一台主机上切换到root模式后,在编译内核的位置执行以下操作:\ngdb vmlinuz即可启动gdb进行调试。\n首先需要加载vmliunz符号(虽然因为有info的缘故文件较大),\n之后则会进入gdb等待输入的状态。\n要与远程主机建立连接(尽管这只是一台虚拟机),可以通过以下命令设置:
-
- 这个未来的道路将完全取决于个人的努力与机遇。\n目前的基本通信机制已经基本实现完成。\n虽然Linux环境下中文输入法功能还不十分强大,\n但经过大量实践后发现使用起来也还算得心应手,\n而且打字速度相比以前也有明显的提升。
后记:
我也初学阶段关注kgdb调试,并且这也是我的第一步尝试。恳请大家多包涵,请各位多多指导。
虚拟机这种设备有时确实让人感到困惑。同样的配置我在深夜尝试了多次却没有成功地配置好串口,在第二天早晨却意外地正常工作起来。难以想象这样的问题竟然会在这么短的时间内解决。
