【问题标题】:Issue with qemu and gdbqemu 和 gdb 的问题
【发布时间】:2013-02-18 19:54:14
【问题描述】:

我有一个冻结操作系统的设备驱动程序。鼠标甚至不会移动。我正在尝试调试这个问题,我相信一种好的方法是将 gdb 与 qemu 一起使用,这是我以前从未使用过的两件事。有更好的方法吗?

所以首先我需要用我已经完成的调试符号编译内核。

现在,生成了一个名为 vmlinux 的新文件,它与源文件位于同一文件夹中。看来我还需要一个 bzImage 文件according to this,这样我就可以使用以下命令运行新编译的内核:

qemu-system-i386 -kernel bzImage 

或处于调试模式

qemu-system-i386 -s -S -kernel bzImage

我找不到 bzImage 文件。我在哪里可以找到它或这里缺少什么? bzImage 是指我使用 qemu-img create 创建的 OS Image 吗?

另外,我不明白的是现在内核已经编译(vmlinux)我如何用qemu运行它?所以我的问题是,当我使用 qemu 或调试器运行它时,内核是否在我的主操作系统中作为应用程序运行?

我如何安装我的设备驱动程序?我的理解内核不是Ubuntu所以没有UI?

另外,我安装了 qemu,当我输入 qemu 时,我得到 command not found。我猜我必须选择一个特定的处理器模拟器,如 qemu-system-i386、qemu-system-x86_64 或 qemu-x86_64?

qemu 与 kvm 命令有何不同或相似之处?

谢谢。

【问题讨论】:

  • 您可能在系统死机后重新启动系统时查看了系统日志?那里有关于内核错误的消息吗?如果你没有,我建议你这样做。有时,从分析系统日志开始可能比按照您描述的路线更容易。
  • 如果系统日志中没有保存故障信息,可以尝试其他方式获取。如果有故障的驱动程序可以在虚拟机的来宾操作系统(您似乎使用 Ubuntu)中运行,您可以在启动时配置该操作系统以将日志输出到串行端口并从主机上从那里检索它。如果驱动程序用于虚拟机不支持的硬件,QEMU 也无济于事。
  • 关于 QEMU 和 KVM,请查看它们的官方网站:QEMUKVM。简而言之,QEMU 允许创建虚拟机,它模拟目标系统。当与 KVM(一组特殊的内核模块等)一起使用时,QEMU 能够使用主机 CPU 的虚拟化支持而不是仿真,从而实现在 VM 中运行的操作系统的更好性能。
  • kern.log 中没有任何内容。不确定我是否应该查看其他文件。我只是在猜测,但我认为这是一个死锁而不是崩溃,这就是为什么 kern.log 中可能没有任何内容。
  • 驱动程序甚至不是硬件,它是一个跟踪工具,可以拦截文件系统调用并基本上记录它们。然后驱动程序进行较低级别的文件系统调用以执行实际操作。如果我可以记录“文件系统”调用(在 ext3-4 级别),实际上对我来说更好。因此,如果有一种方法可以跟踪那些也可以解决我的问题的调用。谢谢。

标签: linux-kernel gdb qemu


【解决方案1】:

所以,如果我正确理解了这个问题,那么您有一个不需要特定硬件的内核模块。当您使用该模块时,系统会冻结,但内核日志没有任何特殊内容。

以下内容可能会有所帮助。

获取日志

您描述的症状可能仍然是内核 oops 或恐慌的结果。日志记录工具有时在将有关错误的信息输出到日志文件之前就死了。您可以尝试通过串口输出日志,这样应该更可靠。

由于您的内核模块不需要任何特定硬件,因此最简单的方法可能是安装与您使用的虚拟机相同的 Linux 发行版,并将该机器的虚拟串行端口 (COM) 连接到主机上的管道系统。

这通常很容易做到。例如,this blog post 包含主机操作系统和客户操作系统为 Ubuntu 11.10 的详细说明。

VirtualBox 用于管理虚拟机。如果您更喜欢 QEMU,这也应该是可能的。我认为使用 VirtualBox 会更容易一些,但这是个人喜好问题。

基本上,您需要执行以下步骤。

  • 创建一个虚拟机并在其中安装您需要的 Linux 发行版作为来宾操作系统。
  • 在虚拟机的配置中启用串行端口(COM1,...)并将其配置为连接到主机上的特殊文件(“主机管道”),例如 /tmp/vbox_serial
  • 启动客户机操作系统并调整其引导选项:至少,在引导加载程序菜单的内核选项中添加console=ttyS0,115200 或类似内容。
  • 在主机上,启动 minicomsocat 或从 /tmp/vbox_serial 读取的任何其他内容。
  • 就是这样。现在您应该通过/tmp/vbox_serial 获取来宾操作系统的内核日志涌入您的主机系统。如果来宾系统崩溃,您将获得日志,即使它没有保存到来宾本身的文件中。

为方便起见,您可以在主机系统上使用socat,而不是该博文作者建议的minicomminicom 的力量在这里可能不需要。

这样,您可以使用socattee 将日志保存到guest.log 文件,同时仍将其输出到控制台:

socat /tmp/vbox_serial - | tee guest.log

如果出现内核 oops 或 panic,日志中的回溯通常有助于找出是什么 出错了。

检测死锁

如果您通过串行连接或其他方式获得了完整的日志,但仍然没有任何可疑之处,并且您怀疑内核中存在死锁, lockdep 工具可能会有所帮助。它包含在内核中(但您可能需要使用CONFIG_LOCKDEP_SUPPORT=y 重新构建内核)。

Lockdep 检测潜在的死锁并将结果输出到内核日志。 This presentation 可以帮助你分析它的输出。

追踪设施

如果您需要跟踪内核中的某些事件来调试您的系统,有一些工具可能会很方便。

  • Kprobes - 一种可以在内核中几乎任意位置设置的断点。可用于跟踪函数调用等,对性能有中等影响。
  • SystemTap - 一个强大的系统来分析内核中发生的事情。其中一部分基于 Kprobes。
  • Ftrace - 一个包含在内核中的跟踪系统,如果重要的话,它比 Kprobes 产生的开销更少。

【讨论】:

  • 谢谢。我有个问题。通过串口打印什么?我看到的是内核消息(kern.log)的一部分,而不是全部。奇怪的是,我的模块打印了一堆语句(每个文件调用大约 50 个),并且只有一对被打印到串行端口。但是,在 kern.log 中都存在。即使是启动消息,也不是全部都在那里。实际上有些出现在 minicom 中,但没有出现在 kern.log 中,反之亦然。那么我在这里错过了什么?再次感谢。
  • 没有看到你的代码就很难猜到。也许,它与您用于打印这些消息的日志级别有关(KERN_INFOKERN_ERR 等在printk()pr_*() 围绕printk 的包装器)。这取决于内核设置,哪些消息打印到控制台(包括串行控制台),哪些消息打印到日志文件。通常KERN_CRIT 或更高级别的消息都会发送到控制台和日志文件,其余的 - 仅发送到日志文件。您可以尝试在启动时在console=ttyS0 之后添加ignore_loglevel 内核选项。
  • (续)这样所有消息都应该发送到串行控制台。至于日志文件中缺少的消息 - 正如我之前建议的那样,日志守护程序并不总是成功地将消息保存在日志文件中,尤其是。如果内核或驱动程序发生错误。串口输出更可靠。
  • 是的。我注意到 printk 中的 KERN_CRIT。所以我终于把猜测的操作系统冻结了,并从 minicom 那里得到了一些反馈,我将在下一条评论中粘贴这些反馈。所以它看起来像 netbeans 的死锁,虽然我不知道为什么。
  • [108.276531] 进程 java (pid: 1837, ti=e8824000 task=e880b2c0 task.ti=e8824) [108.276531] 堆栈: [108.276531] 调用跟踪: [108.276531] 代码: 90 b8 43 46 03 c1 b9 40 64 03 c1 e9 49 ff ff ff 90 55 ba 0 [ 136.272032] BUG:软锁定 - CPU#0 卡住了 22 秒! [java:1837] 和另一个但以这个结尾:[142.920010] 信息:rcu_sched 检测到 CPU 0 上的停顿(t=15000 jiffies)。感谢你的帮助。真的很感激。
猜你喜欢
  • 1970-01-01
  • 2019-09-30
  • 1970-01-01
  • 2019-12-29
  • 2015-03-04
  • 2011-06-09
  • 2013-07-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多