【问题标题】:how qemu-kvm create a VM thread internally?qemu-kvm 如何在内部创建 VM 线程?
【发布时间】:2012-06-06 21:19:08
【问题描述】:

现在我正在做一个关于 qemu-kvm 和 linux 任务调度程序的项目。我知道每个 VCPU 都是由 qemu 创建到 linux 操作系统的正常任务。然后我尝试执行 qemu 命令,看看任务是如何创建的。我使用 strace 来跟踪所有的系统调用。没有“fork”或“pthreadcreate”之类的东西。但我已经看到了:

open("/dev/kvm", O_RDWR|O_LARGEFILE)    = 3
ioctl(3, KVM_GET_API_VERSION, 0)        = 12
ioctl(3, KVM_CHECK_EXTENSION, 0x19)     = 0
ioctl(3, KVM_CREATE_VM, 0)              = 4
ioctl(3, KVM_CHECK_EXTENSION, 0x4)      = 1
ioctl(3, KVM_CHECK_EXTENSION, 0x4)      = 1
ioctl(4, KVM_SET_TSS_ADDR, 0xfffbd000)  = 0
ioctl(3, KVM_CHECK_EXTENSION, 0x25)     = 0
ioctl(3, KVM_CHECK_EXTENSION, 0xb)      = 1
ioctl(4, KVM_CREATE_PIT, 0xb)           = 0
ioctl(3, KVM_CHECK_EXTENSION, 0xf)      = 2
ioctl(3, KVM_CHECK_EXTENSION, 0x3)      = 1
ioctl(3, KVM_CHECK_EXTENSION, 0)        = 1
ioctl(4, KVM_CREATE_IRQCHIP, 0)         = 0
ioctl(3, KVM_CHECK_EXTENSION, 0x1a)     = 0

看起来它打开了设备 /dev/kvm 并执行了一些 ioctl 系统调用。我相信这是实际创建 VM 线程的地方。对?我是操作系统的新手,如果有人能给我一些线索,我将不胜感激:>谢谢

【问题讨论】:

  • @duskwuff 但是据我所知,在 KVM 中,VM 中的每个 VCPU 都是主机 linux 看到的一个线程
  • 不完全是。每个 VCPU 只是一个单独的可运行对象。有关 KVM ioctls 的详细信息,请参阅mjmwired.net/kernel/Documentation/kvm/api.txt
  • @duskwuff 嗨。我已经检查了文档。它真的很有帮助。谢谢。我看到有一个 ioctl(KVM_RUN) 调用。我想也许这就是启动 vcpu 进程的调用。然后我跟踪了 qemu 和 kvm 源代码。我已经看到这个调用将调用另一个名为 kvm_arch_vcpu_ioctl_run 的函数,该函数将根据不同的架构而有所不同。但我仍然找不到像 fork() 这样的系统调用。通常我想在代码中找到 qemu-kvm 何时为新的 vcpu 分叉一个线程:>
  • 你为什么期待一个 fork() 系统调用? pthread_create() 不使用 fork()。你跟踪 clone() 系统调用了吗?

标签: linux qemu kvm


【解决方案1】:

VCPU 既不是操作系统线程也不是进程。要了解 VCPU 的工作原理,首先我们应该弄清楚来宾操作系统是如何在 Intel VT-x 架构上运行的。

Intel VT-x 提出了一种新的模式方法,有两种模式:VMX root modeVMX non-root mode,分别用于运行主机 VMM 和来宾。 Intel VT-x 还包含一个新结构:VMCS,它保存了主人和客人需要的所有信息。 VMCS 是每位客人一个。

KVM 是一个硬件辅助的虚拟机管理程序,并利用 Intel VT-x。主机 Linux KVM 在VMX root mode 中运行。当 KVM 决定切换 CPU 模式来运行客户机时,KVM 会将所有当前上下文转储到VMCS 并执行“VMLAUNCH”指令。 “VMLAUNCH”会将 CPU 从VMX root mode 转移到VMX non-root mode,并从 VMCS 加载来宾上下文,然后启动或继续执行来宾代码。

总之,来宾代码直接在VMX non-root mode 的CPU 上运行。不需要 VCPU 的软件仿真层。这就是为什么 KVM 具有更好的性能,并且没有针对 guest 的特定线程。

/dev/kvm是由kvm.ko创建的,这只是QEMU的KVM接口。您的strace 输出显示了 QEMU 如何与 KVM 交互并控制底层客户机。您永远无法在 KVM 中找到 forkclone 系统调用。

如需更多 KVM 细节,尤其是 VCPU,您可以阅读 arch/x86/kvm/vmx.c 中的 KVM 代码,了解更多基于 Intel VT-x 的 VCPU 实现细节。

【讨论】:

    【解决方案2】:

    尽管 VCPU 是不同于线程或进程的 OS 对象,并且 VCPU 对象是使用 KVM_CREATE_VCPU ioctl 创建的,但 QEMU 确实是为每个 VCPU 创建一个线程。当 QEMU 从该线程执行 KVM_RUN 时,来宾运行(物理 CPU 进入 VMX 非 root 模式)。 KVM_CREATE_VCPU 返回一个新的文件描述符,这就是您将在 KVM_RUN ioctl 中看到的 fd。

    您的 strace 中可能缺少 VCPU 线程,因为您没有使用 -ff 选项。 -ff 要求 strace 也跟踪除初始线程之外的其他线程。

    【讨论】:

    • 感谢您提及 strace -ff 选项。 #strace 一个进程并跟踪所有分支:strace -ff -p12345
    猜你喜欢
    • 2018-01-19
    • 2015-04-30
    • 2021-01-28
    • 2021-05-13
    • 1970-01-01
    • 1970-01-01
    • 2019-05-15
    • 1970-01-01
    • 2021-10-21
    相关资源
    最近更新 更多