Skip to content

Virtio

Virtio 是一套实现虚拟化设备的通用协议,它是 hypervisor 和操作系统驱动之间沟通的桥梁。只要遵循 virtio 协议进行设备模拟,就能坐享海量生态资源,实现虚拟设备自由。

架构概述

Virtio 采用前后端分离的架构设计:

  • 前端(Frontend):运行在 Guest OS 中的驱动程序
  • 后端(Backend):运行在 Hypervisor 中的设备模拟实现
  • 通信机制:通过 virtqueue 实现前后端的数据交换

前后端分离

Virtio 设备的通信是侵入式的,它要求 Guest OS 支持和安装 virtio 设备的驱动。

Linux 默认自带了 virtio 协议族的驱动,使用 virtio 模型可以复用大量的驱动代码;QEMU 支持了大量的 virtio 设备,使用 virtio 模型可以复用大量的设备虚拟化代码。

Virtqueue 和 Vring

Virtio 通过 virtqueue 数据结构进行前后端的交互,其核心机制是内部的 vring 数据结构。一个 virtqueue 对应一个 vring,一个 vring 是一个数组,被分成三个独立部分:

  1. Descriptor Table(描述符表)

    • 数据准备区
    • 只能由前端写入交互信息
    • 后端只读
    • 包含数据缓冲区的地址和长度信息
  2. Available Ring(可用环)

    • 前端通知区
    • 前端可写,后端只读
    • 用于前端通知后端有新的请求待处理
  3. Used Ring(已用环)

    • 后端通知区
    • 后端可写,前端只读
    • 用于后端通知前端请求处理完成

环形缓冲区机制

  1. 索引管理

    • Available Ring 和 Used Ring 各自有一个 idx(索引)
    • 分别由前端和后端维护
    • 这些索引像"指针",标记环形缓冲区的写入位置
    • 确保前后端不会覆盖彼此的数据
  2. 环形设计

    • Available Ring 和 Used Ring 采用环形设计
    • 前后端可以在各自的环中独立推进
    • 前端可以在 Available Ring 中填入新请求
    • 后端在 Used Ring 中标记已完成的任务
  3. 通知机制

    • 前端通过"kick"(通知后端)触发处理
    • 后端通过中断(通知前端)反馈结果
    • 这种异步通知避免了忙等待
    • 提升并发效率

多队列支持

一个设备可以创建多个队列,每个队列彼此独立,由前后端在通信时并行使用,从而提高设备的吞吐效率。

队列类型

  1. 单队列

    • 简单的设备采用单队列即可完成基本需求
    • 一个 virtqueue 是半双工的
  2. 双队列

    • 为了提高数据传输效率
    • 一个作为 tx_queue(发送队列)
    • 一个作为 rx_queue(接收队列)
    • 实现双向的全双工数据传输
  3. 多队列

    • 采用负载均衡的分发策略
    • 提高设备和驱动之间的吞吐能力
    • 特别适合高性能网络设备

注意:对于网络设备,传输速度取决于整条链路上的瓶颈点,单一一处的吞吐量大不能保证网速的提升。

设备初始化流程

  1. 设备发现

    • Guest OS 通过 PCI 或 MMIO 发现 virtio 设备
    • 读取设备配置空间获取设备信息
  2. 设备配置

    • 协商特性(Feature bits)
    • 设置设备参数
    • 分配 virtqueue
  3. 驱动加载

    • 加载对应的 virtio 驱动
    • 初始化驱动数据结构
    • 建立与设备的通信通道
  4. 设备就绪

    • 完成所有初始化步骤
    • 设备进入工作状态
    • 可以开始处理 I/O 请求

前后端通信流程

  1. 数据发送流程

    • 前端准备数据缓冲区
    • 将缓冲区信息写入 Descriptor Table
    • 更新 Available Ring 的索引
    • 发送 kick 通知后端
  2. 数据接收流程

    • 后端处理请求
    • 将结果写入 Used Ring
    • 发送中断通知前端
    • 前端处理完成通知

数据面和控制面

数据面

  1. 数据传输

    • 通过 virtqueue 进行批量数据传输
    • 支持零拷贝技术
    • 高效的内存映射机制
  2. 性能优化

    • 批量处理请求
    • 异步通知机制
    • 多队列并行处理

控制面

  1. 设备管理

    • 设备状态监控
    • 配置更新
    • 错误处理
  2. 特性协商

    • 前后端特性协商
    • 协议版本管理
    • 扩展功能支持

Virtio 设备类型

  1. 网络设备(virtio-net)

    • 虚拟网卡
    • 支持多队列
    • 支持 TSO/GSO
  2. 块设备(virtio-blk)

    • 虚拟磁盘
    • 支持多队列
    • 支持 DISCARD/WRITE_ZEROES
  3. 控制台设备(virtio-console)

    • 虚拟串口
    • 支持多端口
    • 支持流控制
  4. 输入设备(virtio-input)

    • 虚拟键盘/鼠标
    • 支持事件上报
    • 支持多点触控
  5. GPU 设备(virtio-gpu)

    • 虚拟显卡
    • 支持 2D/3D 加速
    • 支持显示输出

性能优化

  1. 批处理

    • 合并多个 I/O 请求
    • 减少前后端交互次数
    • 提高吞吐量
  2. 零拷贝

    • 避免数据在内存中的复制
    • 直接使用共享内存
    • 降低 CPU 开销
  3. 中断合并

    • 合并多个中断为一个
    • 减少中断处理开销
    • 提高系统响应性
  4. 轮询模式

    • 在特定场景下使用轮询
    • 减少中断开销
    • 提高低延迟场景性能

安全考虑

  1. 内存隔离

    • 前后端内存空间隔离
    • 防止越界访问
    • 保护敏感数据
  2. 权限控制

    • 设备访问权限管理
    • 资源配额限制
    • 防止资源耗尽
  3. 数据加密

    • 敏感数据传输加密
    • 密钥管理
    • 安全协议支持