vhost-user如何虚拟化

联启 网络工具 15

本文目录导读:

vhost-user如何虚拟化-第1张图片-电脑手机工具软件下载 - 免费实用工具合集 | 联启科技

  1. 背景:传统虚拟化 I/O 的性能瓶颈
  2. vhost-user 的核心架构:谁在做什么?
  3. 工作流程:一次虚拟化 I/O 全过程
  4. 为什么 vhost-user 能做到“虚拟化”?
  5. 优缺点与适用场景

这是一个关于 vhost-user 如何实现设备虚拟化的深度技术问题。vhost-user 是一种通过共享内存和 Unix 域套接字,将虚拟设备的 I/O 处理从 Hypervisor(如 QEMU)卸载到外部用户态进程的机制

它的核心目标是解决传统虚拟化 I/O 路径长、性能差的问题,同时比内核态的 vhost 方案(如 vhost-net)更灵活、更安全。

为了让你彻底理解,我将从“解决了什么问题”、“核心架构”和“工作流程”三个层面来拆解。


背景:传统虚拟化 I/O 的性能瓶颈

在传统的 QEMU + 内核 vhost 模式中,数据路径大致如下:

  1. Guest VM 的驱动发送数据包。
  2. 数据通过 virtio 协议进入 QEMU 的用户态。
  3. QEMU 通过 ioctl 进入 Linux 内核的 vhost 驱动。
  4. 内核 vhost 直接与物理设备(如网卡、NVMe 磁盘)交互,完成 DMA 传输。

痛点:

  • 每次 I/O 仍涉及 VMM(QEMU)到内核的上下文切换(ioctl)。
  • QEMU 成为性能瓶颈,因为它仍然要参与管理控制。

vhost-user 的方案: 彻底砍掉 QEMU 这个“中间商”,让第三方进程(如 DPDK 的 vSwitch、SPDK 的存储控制器)直接与 Guest VM 通过共享内存交换数据。


vhost-user 的核心架构:谁在做什么?

vhost-user 系统主要由三部分组成:

组件 角色 具体实现
前端 (Front-end) Guest VM 内部的驱动 标准的 virtio 驱动,virtio-netvirtio-blk,它“以为”自己在跟一个真实的物理设备通信。
后端 (Back-end) 外部用户态进程 负责实际处理 I/O 的进程,Open vSwitch (OVS-DPDK)、SPDK vhost-blk 进程,它“扮演”了物理设备的功能。
Virtio 队列 (Virtqueues) 共享内存区域 Guest OS 和 Back-end 进程通过 mmap 共享的物理内存(通常是大页内存),这是数据传输的“高速公路”。
控制通道 Unix 域套接字 QEMU 和 Back-end 进程之间通过 Unix Socket 通信,用于协商配置(如内存区域地址、队列数量、启动/停止)。

关键点: QEMU 不再参与数据传输,仅负责初始化管理,数据传输是 Guest <-> Back-end 的直接内存拷贝。


工作流程:一次虚拟化 I/O 全过程

vhost-user-net(Guest 发送一个网络包)为例:

初始化(通过 Unix Socket 协商)

  1. QEMU 启动:QEMU 创建一个 Unix Socket(/var/run/vhost-user.sock)。
  2. Back-end 连接:DPDK 的 OVS 进程(作为 Back-end)连接到这个 Socket。
  3. 协商
    • QEMU 告诉 Back-end:我的虚拟机内存在物理地址空间哪里,你的队列应该在哪个位置。
    • Back-end 通过 mmap 将 Guest 的内存镜像到自己的进程地址空间。
    • 双方协商 Virtio 队列的数量和参数(如 Queue Size)。
    • 控制权移交:初始化完成后,QEMU 不再干预后续的 I/O。

数据传输(通过共享内存直连)

  1. Guest 发送包:Guest 内的 virtio-net 驱动将待发送的数据包放入 Tx Virtqueue(写虚队列),并写入一个门铃 (Doorbell)。
  2. 信号通知:这个门铃会直接写入 Back-end 进程的 Eventfd 事件文件(通过 KVM 的虚拟化中断机制触发,或者 PMD 轮询模式中直接轮询)。
  3. Back-end 处理(DPDK Back-end)
    • Back-end 进程监控到 Eventfd 或轮询到队列变化。
    • 它直接从共享内存中读取数据包,而不需要拷贝(零拷贝)。
    • 它模拟物理网卡的 DMA 行为,将数据包发送到物理网卡(如果是网卡)或处理(如果是虚拟交换机)。
  4. 中断注入:处理完成后,Back-end 通过 KVM 向 Guest 注入一个完成中断,告知驱动可以回收此描述符。

整个过程:

  • QEMU 没有参与任何数据拷贝
  • 没有内核态介入(除了 KVM 的中断注入)。
  • 性能远高于传统 virtio(KVM-QEMU 模式)。

为什么 vhost-user 能做到“虚拟化”?

vhost-user 的“虚拟化”主要体现在它对 PCI 设备 的模拟:

  1. 设备模拟:Back-end 进程在共享内存中模拟了 Virtio PCI 配置空间(BAR 地址空间),Guest 的 virtio 驱动初始化时,会通过 QEMU 模拟的 PCI 设备读取这些配置,从而知道如何找到共享内存和队列。
  2. 中断机制:Back-end 通过 KVM 的 IOCTL_KVM_IRQFD 功能,能够直接向 Guest 注入虚拟中断(MSI-X),这模拟了物理设备完成 I/O 后触发中断的过程。
  3. DMA 模拟:Back-end 通过 mmap 共享 Guest 内存,它只需要修改指针、拷贝数据,对于 Guest 就像物理设备的 DMA 引擎从内存中读写了数据。

一句话总结它的虚拟化逻辑:

物理设备 = CPU(处理逻辑) + MMIO/BAR(配置接口) + DMA(数据通路) + 中断(通知机制)。 vhost-user = 用户态进程(CPU) + 共享内存(DMA) + KVM 中断注入(中断) + Unix Socket(配置接口)。


优缺点与适用场景

优点:

  • 极致性能:接近原生(通常损耗 < 5%),尤其在 DPDK/SPDK 的 PMD 轮询模式下。
  • 隔离性:Back-end 崩溃不会影响 VMM 本身(QEMU),反之亦然(如果实现正确)。
  • 扩展性:可以很容易用不同的 Back-end(不同的 vSwitch、不同的存储引擎)替换,QEMU 不需要改动。

缺点:

  • 复杂度:配置复杂,需要 mmap 大页内存、设置 Unix Socket。
  • CPU 开销:Back-end 采用轮询模式,会吃掉 100% 的 CPU 核心,不适合 CPU 密集部署。
  • 内核模块依赖:虽然 Back-end 在用户态,但底层仍依赖 KVM 的虚拟化特性(中断注入、EPT 页表)。

主要应用场景:

  • NFV(网络功能虚拟化):如虚拟 BRAS、虚拟防火墙、核心网网元,要求超高吞吐量。
  • 高性能存储:如 SPDK 提供的虚拟 NVMe 控制器,用于数据库、容器存储。
  • 容器网络(如 Kata Containers):轻量级 VM 内的网络加速。

vhost-user 是一种 “卸载 + 共享内存” 的虚拟化方案,它不是传统意义上的硬件虚拟化,而是一种软件层面的、高效的用户态 I/O 虚拟化,它通过将 I/O 控制面(管理)交由 QEMU 处理,数据面(传输)交由第三方高性能用户态进程通过共享内存直接处理,实现了接近物理设备性能的虚拟化 I/O。

标签: user 协议

抱歉,评论功能暂时关闭!