我了解内核模式和用户模式的目的,以及从前者到后者的转换是如何发生的。然而,许多消息来源指出,内核模式下发生的崩溃很难调试,应该远程完成,例如通过 telnet 连接(这里是一个示例)。
为什么调试这么难?为什么不能将(内核)调试器附加到其中一个内核线程并以通常的方式使用它?
我了解内核模式和用户模式的目的,以及从前者到后者的转换是如何发生的。然而,许多消息来源指出,内核模式下发生的崩溃很难调试,应该远程完成,例如通过 telnet 连接(这里是一个示例)。
为什么调试这么难?为什么不能将(内核)调试器附加到其中一个内核线程并以通常的方式使用它?
在内核模式下崩溃可能会破坏内存中任何地方的数据结构,甚至是调试器本身。做到防弹是很难的。
在正常的调试中,你有两个完全隔离的进程——调试器和你正在调试的东西。他们是“同龄人”,生而平等。被调试的进程无法触及调试器,无论它做什么(并且可能甚至不知道它存在)。另一方面,调试器可以以固定的、可预测的方式与被调试的进程交互,这些方式始终适用于所有常规用户进程。
一个例子:如果是本地调试,您将如何调试键盘接口,或者如果通过串行端口调试 RS232 代码?NIC 驱动程序或网络堆栈(如果它通过网络)?在其中一个中设置断点将无法恢复,因为您将无法访问控制调试器的设备。最坏的情况,您将如何调试内核调试器?使用 GDB,您至少在理论上可以将 GDB 实例附加到另一个 GDB 实例而不会带来太多麻烦。在内核空间中这是不可能的,因为上面没有层来调解事情。
您不能以交互方式(或本地)调试内核,因为内核本身甚至负责在监视器上显示图片(通过与适当的显示驱动程序通信)等等。我会以另一种方式提出您的问题:调试内核是否比通过 telnet 连接更容易?
对于这个问题,我的回答是:是的,是的。至少在 X86/X64 架构上使用虚拟化。我正在使用 VirtualBox 运行可以在本地计算机上调试的来宾操作系统。我还使用了 VirtualKD (http://virtualkd.sysprogs.org/),它大大加快了调试机器(主机)和 VM 之间的通信速度。
VirtualKD 包含一个修改来宾 Windows 的 boot.ini 的软件包,因此您可以通过选择 Windows 显示给您的正确菜单项在启动时启用调试。