【问题标题】:Why is debugging in kernel mode difficult?为什么在内核模式下调试很困难?
【发布时间】:2012-01-05 17:48:35
【问题描述】:

我了解内核模式和用户模式的用途,以及从前者到后者的转换是如何发生的。然而,许多消息来源指出,内核模式下发生的崩溃很难调试,应该远程完成,例如通过 telnet 连接 (here is an example)。

为什么调试这么难? 为什么不能将(内核)调试器附加到其中一个内核线程并以通常的方式使用它?

【问题讨论】:

    标签: operating-system computer-architecture kernel-mode


    【解决方案1】:

    在内核模式下崩溃可能会损坏内存中任何地方的数据结构,甚至是调试器本身。防弹是很难的。

    在正常调试中,您有两个完全隔离的进程 - 调试器和您正在调试的东西。他们是“同龄人”,生而平等。被调试的进程无法触及调试器,无论它做什么(并且可能甚至不知道它存在)。另一方面,调试器可以以固定的、可预测的方式与被调试的进程交互,这些方式始终适用于所有常规用户进程。

    一个例子:如果是本地调试,您将如何调试键盘接口,或者如果通过串行端口调试 RS232 代码? NIC 驱动程序或网络堆栈(如果它通过网络)?在其中一个中设置断点将无法恢复,因为您将无法访问控制调试器的设备。最坏的情况,您将如何调试内核调试器?使用 GDB,您至少在理论上可以将 GDB 实例附加到另一个 GDB 实例而不会带来太多麻烦。在内核空间中这是不可能的,因为上面没有层来调解事情。

    【讨论】:

    • 好的,我想我明白了。如果我弄错了,请纠正我:这是否意味着所有在内核模式下运行的进程共享相同的地址空间?如果这是真的,那有什么理由吗?
    • 是的,内核地址空间在所有进程之间共享。如果你有 Linux 内核的通用内核代码(不是特定设备的驱动程序),你可以使用 QEMU。您可以将 gdb 附加到在 QEMU 上运行的软件,因此您可以像使用 gdb 的用户代码一样单步执行内核代码。但是,如果您的代码特定于设备,例如设备驱动程序,而没有可用的仿真,您的软件将不会执行。
    • @user420536 这个问题实际上并没有指定 Linux 或什么架构。有些情况非常不同。
    • @awoodland -- 世界上的内核肯定比 linux 内核多。我在回复中提到了两件事,a)地址空间在内核中为所有进程共享,并且对所有内核都是如此。 b) 以 QEMU 为例,将调试器附加到内核,这是 OP 想要的方式及其局限性。
    【解决方案2】:

    您不能以交互方式(或本地)调试内核,因为内核本身负责在监视器上显示图片(通过与适当的显示驱动程序通信),而且不仅如此。我会用另一种方式提出你的问题:调试内核是否比通过 telnet 连接更容易?

    对于这个问题,我的回答是:是的。至少在 X86/X64 架构上使用虚拟化。我正在使用 VirtualBox 运行可以在本地计算机上调试的来宾操作系统。我还在使用 VirtualKD (http://virtualkd.sysprogs.org/),它极大地加快了调试机器(主机)和 VM 之间的通信。

    VirtualKD 包含一个修改来宾 Windows 的 boot.ini 的包,因此您可以通过选择 Windows 显示给您的适当菜单项在启动时启用调试。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-03-05
      • 1970-01-01
      • 1970-01-01
      • 2020-06-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多