![如果有硬件辅助虚拟化,那么使用半虚拟化的目的是什么?](https://linux22.com/image/793105/%E5%A6%82%E6%9E%9C%E6%9C%89%E7%A1%AC%E4%BB%B6%E8%BE%85%E5%8A%A9%E8%99%9A%E6%8B%9F%E5%8C%96%EF%BC%8C%E9%82%A3%E4%B9%88%E4%BD%BF%E7%94%A8%E5%8D%8A%E8%99%9A%E6%8B%9F%E5%8C%96%E7%9A%84%E7%9B%AE%E7%9A%84%E6%98%AF%E4%BB%80%E4%B9%88%EF%BC%9F.png)
我正在研究 QEMU/KVM 和 Firecracker/KVM。据我所知,Firecracker 和 QEMU 都与 KVM 通信,最终通过将 CPU 模式从客户机更改为主机(反之亦然)来实现硬件辅助虚拟化。
在CPU的客户模式下,客户甚至可以直接执行其特权指令,那么我们为什么还需要半虚拟化呢?
在 Firecracker 中,仅模拟了 5 种设备,例如
- virtio-net,
- virtio 块,
- virtio-vsock等等。
即使是在这种极简设计中,我们也必须安装半虚拟化驱动程序。难道我们不能只依赖硬件辅助虚拟化吗?
答案1
仅考虑网络的情况。
在大多数情况下,要真正发挥作用,虚拟机需要能够通过网络进行通信。为此,客户机显然必须看到某种网络接口。但 VT-x、AMD-V、ARM VHE 以及几乎所有其他硬件虚拟化实现都不提供 NIC,它们只是为您提供了一种安全隔离和划分 CPU 资源的方法。因此,硬件虚拟化不会为您提供网络接口。
现在,您可以通过主机系统传递物理网络接口,但这存在一些问题:
- 它需要主机操作系统在启动时进行特殊处理,以确保它实际上不会将驱动程序绑定到该接口。
- 它需要硬件的特殊支持才能保证安全(你需要IOMMU,并且您想要通过的 NIC 必须支持在 IOMMU 后面运行)。
- 它实际上需要具有每个 VM 都有一个可用的网络接口。这显然意味着使用笔记本电脑的人将不会有好运,但这也意味着大多数大型 VM 托管提供商也将不会有好运(他们可能在同一台主机上运行数十台 VM)。
- 如果没有 RDMA 硬件和大量额外的复杂性(就像任何其他直接设备直通一样),实时迁移在功能上就不可能实现。
- 如果虚拟机需要相互通信,则会固有引入外部故障点(因为它们必须通过系统外部的网络交换机发送流量)。
所以你显然需要仿真网络接口。显而易见的选择是选择一个常用的物理 NIC 并模拟它。但这有它自己的一系列问题:
- 物理网卡的很多功能在模拟时需要耗费相当多的计算资源。只有在物理实现中才会高效因为它使用物理逻辑和 ASIC。
- 大多数同样的东西,模仿起来很昂贵,甚至需要对于虚拟机来说,但你无法避免模拟它,因为驱动程序希望它能够工作。
- 为支持这些甚至没有带来任何实际好处的东西,客户驱动程序需要增加很多复杂性。从这个角度来看,Linux 的 Intel e1000(一种常见的模拟物理 NIC)驱动程序大约有 17k 行代码,而 virtio-net 驱动程序只有 4.8k 行代码(如果包括它可能在 x86 系统上使用的 virtio-pci 组件,则为 7.3k 行)。
virtio-net 解决了这些问题,它只涵盖了在客户操作系统和主机网络层之间移动网络数据包的实际需要,仅此而已。解决这些问题提供了一个巨大的性能改进。我最近没有测试过,但上次使用 QEMU 进行比较时,virtio-net 提供的有效带宽是模拟 e1000 卡的两倍多,延迟大约是其十分之一,而且主机端的 CPU 使用率更低。
同样的逻辑也适用于大多数其他设备。有些东西可以相对便宜地模拟,或者对性能要求不高,因此不需要高效(这就是为什么没有 VirtIO 看门狗定时器的原因,它对性能要求不高,而且在大多数情况下模拟起来很容易),但对于大多数不符合这些标准的东西,有一个 paravirt 选项,因为性能差异很大,而且复杂性的降低往往会使事情变得更加可靠。
有时半虚拟化可以让你做一些用“常规”硬件无法做到的事情。VirtIOFS 和 9P2000 的 VirtIO 传输就是最好的例子,它们没有硬件类似物,但提供了一种在主机和客户机之间共享文件的合理有效方法,而无需模拟网络或块设备。
答案2
简短回答:当使用客户机端驱动程序进行增强时,现代硬件虚拟化会使用某种形式的半虚拟化来执行性能最密集的操作。因此,现代虚拟机管理程序会收集两个都来自专用硬件支持和半虚拟化。
长版本:原始的 X86 架构很难在未修改的操作系统上正确虚拟化和使用。一种解决方案是动态翻译有问题的代码片段,并在运行中重新编译它们。这使得未修改的客户机能够运行,但缺点是翻译器本身的开销和复杂性很高。此外,每种客户机内核类型都需要特殊处理。
出于这个原因,项目开始修改Linux内核以避免困难的情况 - 例如:当一条指令/调用不容易虚拟化时,让我们调用一个超级调用来自底层虚拟机管理程序。超级调用是半虚拟化的基础,您可以将其视为用户空间系统调用的等价物。换句话说,底层 Linux 内核是主机操作系统,另一个 Linux 内核将作为客户“用户空间”应用程序运行。
这种方法可以最大限度地减少虚拟化开销,但是需求修改后的客户内核才能工作。您的标准 Windows 安装将无法工作。因此引入了完整的硬件虚拟化,其中向微处理器添加了额外的特权环。这允许主机操作系统在特定的特权级别(即:-1,虚拟机管理程序空间)中运行,而客户操作系统在环 0(即:0,内核空间)中不加更改地运行。但是虚拟设备模拟仍然存在问题和/或开销高,因此创建了自定义客户驱动器。这些驱动器重新引入了针对性能最敏感的设备(特别是磁盘和网络)的定向半虚拟化。这就给我们带来了当前的情况,其中硬件辅助虚拟机管理程序通过定向半虚拟化驱动器得到增强。
答案3
我也做了一些研究,我认为它可能有助于您理解这个问题,但可能没有直接解决这个问题(也许)。除了 shodanshok 的回答,我可能会炸毁他的“扩展”答案,也许占用的空间有点大
半虚拟化(可能)仍然具有相关性,原因如下:
- 性能优化:
尽管特权指令可以直接在客户机模式下执行,但半虚拟化可以通过优化客户机操作系统和虚拟机管理程序之间的通信来提高性能。半虚拟化允许使用专门设计的接口和协议,以实现客户机和虚拟机管理程序之间的高效协作。
- 灵活性和可移植性:
半虚拟化可以对可能未针对在虚拟化环境中直接执行进行优化的客户操作系统进行虚拟化。通过提供特定接口,客户系统可以更轻松地跨各种虚拟化平台移植。
- 安全:
半虚拟化可以通过为客户机和虚拟机管理程序之间的通信提供明确定义的接口来提供安全优势,从而潜在地减少攻击媒介。
- 关于 Firecracker 和类似的极简虚拟化解决方案:
尽管它们使用一组有限的模拟设备运行,但使用半虚拟化可以使客户机和虚拟机管理程序之间的通信更加高效和灵活。即使在极简设计中,半虚拟化驱动程序也可以提高整体性能并优化客户机和虚拟机管理程序之间的交互。因此,即使在这样的环境中,半虚拟化仍然有益
维基百科对此有如下解释:
在计算领域,半虚拟化或类虚拟化是一种虚拟化技术,它为虚拟机提供一个软件接口,该接口与底层硬件软件接口类似但不完全相同。
修改后的接口旨在减少客户机执行操作所花费的时间,这些操作在虚拟环境中比在非虚拟化环境中运行困难得多。半虚拟化提供了专门定义的“钩子”,允许客户机和主机请求和确认这些任务,否则这些任务将在虚拟域中执行(执行性能较差)。成功的半虚拟化平台可以使虚拟机监视器 (VMM) 更简单(通过将关键任务的执行从虚拟域重新定位到主机域),和/或减少虚拟客户机内部机器执行的整体性能下降。
半虚拟化要求客户操作系统明确移植到 para-API 中——不支持半虚拟化的传统操作系统发行版无法在半虚拟化 VMM 上运行。但是,即使在无法修改操作系统的情况下,也可以使用一些组件来实现半虚拟化的许多显著性能优势。例如,Xen Windows GPLPV 项目提供了一套支持半虚拟化的设备驱动程序,旨在安装到在 Xen 虚拟机管理程序上运行的 Microsoft Windows 虚拟客户机中。[1] 此类应用程序往往可以通过半虚拟机接口环境访问。这确保了跨多种加密算法模型的运行模式兼容性,从而允许在半虚拟化框架内无缝集成。
我认为,即使我们可以参考维基百科文章,但仍有一些原因导致您不想将硬件直接暴露给客户,尤其是在销售租用的虚拟机时。
此外,通常情况下,我们希望标准和标准化驱动程序也作为接口。
我们通常不想像以前那样处理驱动程序,而尝试安装 Windows 9x/nt/VIST/XP。但或多或少在标准硬件上也有 7/10/11(它们大多已经具备,有时已包含 VirtIO 支持)。(特别是在 Windows 7 时期之前)。
这就是为什么我们需要更多地了解历史:
维基百科文章的历史部分说道:
Parallels Workstation 操作系统将其等效项称为“超级调用”。所有这些都是同一件事:对下面的虚拟机管理程序的系统调用。此类调用需要“客户”操作系统的支持,而客户操作系统必须具有特定于虚拟机管理程序的代码才能进行此类调用。
“半虚拟化”一词最早出现在与 Denali 虚拟机管理器相关的研究文献中。[4] 该术语还用于描述 Xen、L4、TRANGO、VMware、Wind River 和 XtratuM 虚拟机管理程序。所有这些项目都使用或可以使用半虚拟化技术,通过实现不实现实际 x86 指令集中难以虚拟化部分的虚拟机来支持 x86 硬件上的高性能虚拟机。
虚拟机管理程序提供底层计算机系统的虚拟化。在完全虚拟化中,客户操作系统在虚拟机管理程序上不加修改地运行。但是,通过让客户操作系统与虚拟机管理程序通信可以提高性能和效率。通过允许客户操作系统向虚拟机管理程序表明其意图,两者可以协作以在虚拟机中运行时获得更好的性能。这种类型的通信称为半虚拟化。
2005 年,VMware 提出了一种半虚拟化接口,即虚拟机接口 (VMI),作为客户操作系统和虚拟机管理程序之间的通信机制。此接口支持透明半虚拟化,其中操作系统的单个二进制版本可以在本机硬件或半虚拟化模式下的虚拟机管理程序上运行。
这也让我想起了,内核对它的支持早在 2011 年左右就被放弃了,而从 2008 年开始就引入了 VirtIO(可能是作为继任者)
恕我直言:
与 TCP/IPv4 堆栈类似,它代表了一种旨在无限期延续的遗留技术,即使在部署时无法预见未来的发展。我希望这个扩展答案没有让你的眼睛太疲劳。;)
参考):
- https://en.wikipedia.org/wiki/Paravirtualization
- https://docs.kernel.org/driver-api/virtio/virtio.html#:~:text=Virtio%20is%20an%20open%20standard,spec%20(%5B1%5D)。
- https://docs.oasis-open.org/virtio/virtio/v1.2/virtio-v1.2.html
- https://www.redhat.com/en/blog/virtqueues-and-virtio-ring-how-data-travels
- 很多都是我的品牌
- 并且大量使用知名搜索引擎;)
答案4
其他回答包含:
现在,您可以通过主机系统传递物理网络接口,但这存在一些问题:
- 它实际上要求每个虚拟机都有一个可用的网络接口。这显然意味着使用笔记本电脑的人会很倒霉,但这也意味着大多数大型虚拟机托管提供商也会很倒霉(他们可能在同一台主机上运行数十台虚拟机)。
作为反驳,单根 IO 虚拟化 (SR-IOV)可用于允许物理 PCIe 设备通过 PCIe 总线多次出现。来自上面链接的 NVIDIA(前 Mellanox)页面:
该技术可实现具有独立资源的设备多个虚拟实例。Mellanox 适配器能够为 Mellanox ConnectX® 系列卡中的每个端口公开最多 127 个虚拟实例(虚拟功能 (VF))。然后可以单独配置这些虚拟功能。每个 VF 都可以看作是连接到物理功能的附加设备。它与物理功能共享相同的资源,其端口数等于物理功能的端口数。SR-IOV 通常与SR-IOV 使虚拟机管理程序能够为虚拟机提供对网络资源的直接硬件访问,从而提高其性能。
作为虚拟机托管提供商的一个例子,Amazon Web ServicesLinux 上的增强联网页面包含:
增强网络使用单根 I/O 虚拟化 (SR-IOV) 来提供高性能网络功能支持的实例类型。SR-IOV 是一种设备虚拟化方法,与传统虚拟化网络接口相比,它提供更高的 I/O 性能和更低的 CPU 利用率。增强型网络提供更高的带宽、更高的每秒数据包 (PPS) 性能以及持续更低的实例间延迟。使用增强型网络无需额外付费。