Virtio技术详解:从原理到优化实践
立即解锁
发布时间: 2025-10-26 01:18:10 阅读量: 10 订阅数: 12 AIGC 

# Virtio技术详解:从原理到优化实践
## 1. Virtio概述
在云计算领域,虚拟化技术得到了广泛应用,其中设备虚拟化起着关键作用。由于I/O设备种类繁多,不同厂商支持的功能也各不相同。传统上,服务器使用设备时,需先安装与设备特性紧密相关的驱动程序,再开发软件应用以利用设备特性,这在运维阶段可能与特定设备紧密相关,不利于使用多个设备供应商的开放系统的可扩展性。
Virtio最初是作为软件仿真方法发明的,现已发展成为标准化的设备接口,主流操作系统和应用程序逐渐增加了对Virtio设备的直接支持,这为数据中心的运维带来了便利。
与I/O直通技术(如SR - IOV)相比,Virtio在网络吞吐量、延迟或抖动方面目前不具竞争力。但I/O直通存在一些问题,例如物理网卡接收到的数据包会直接交付给客户机(租户)的接收队列,或者客户机发送队列发送的数据包会直接交付给其他客户机(同一PF的VF)的接收队列,甚至数据包会绕过管理程序直接从物理网卡发送。而在许多场景中,网络数据包必须先由主机(如防火墙、负载均衡器、虚拟交换机)处理后才能传递给客户机。此外,I/O直通不支持具有多个硬件供应商的VM实时迁移,VF接口是特定于供应商的,当前的网卡在云计算的流量分类能力方面也缺乏足够的灵活性。值得注意的是,一些行业参与者已开始在网卡中实现Virtio接口,硬件辅助的Virtio将弥补上述性能差距。
下图展示了数据中心服务器中使用Virtio设备的典型场景:
```mermaid
graph LR
A[物理网卡] --> B[虚拟交换机]
B --> C[VM工作负载]
C --> B
B --> A
B -.-> D[DPDK vhost - user PMD]
C -.-> E[Virtio前端网络设备驱动]
E -.-> F[virtio - net内核模块/DPDK - enabled virtio - pmd]
```
前端和后端通过Virtio的虚拟队列相互交换数据。VM的网络数据先发送到虚拟交换机,经过交换处理后,最终通过物理网卡进入外部网络。
## 2. Virtio规范
Virtio有三个规范版本:0.95、1.0和1.1,这些版本是社区多年努力定义和发展而来的。指定的接口包括PCI(外围组件互连)、MMIO(内存映射I/O)和通道I/O(在规范1.0中新增)。DPDK专注于数据包处理,目前支持PCI接口模式下的virtio - net。
### 2.1 规范版本兼容性
- **Spec 1.0**:与之前的Spec 0.95兼容,将早期定义的模式称为“传统”模式,后期定义的模式称为“现代”模式。传统PCI是目前使用最广泛的模式,现代PCI(即PCIe)在Linux内核4.0及以上版本中得到支持。现代和传统PCI设备在参数和使用模式上有所不同,但在Linux内核4.0中,它们使用相同的Virtio设备驱动程序,驱动程序会根据使用QEMU模拟的PCI设备自动选择,可能是传统模式或现代模式。
- **Spec 1.1**:是一项较新的成果,设计上向后兼容之前的Spec 0.95和1.0。在virtio1.1中,将早期规范中定义的virtqueue布局称为“拆分virtqueue”,并定义了一种新的virtqueue布局,名为“打包virtqueue”。打包virtqueue在Linux内核5.0及以上版本中得到支持。与“传统”设备和“现代”设备的情况类似,“拆分virtqueue”和“打包virtqueue”使用相同的Virtio设备驱动程序,驱动程序会处理设备是否支持“打包virtqueue”。
### 2.2 设备初始化
设备初始化有以下五个步骤,初始化成功后,设备可在客户机中使用:
1. **设备发现**:设备重启(或上电)后,系统会发现设备。Spec 1.1定义/保留了24种Virtio设备,如下表所示:
| Virtio设备ID | Virtio设备 |
| --- | --- |
| 0 | 保留(无效) |
| 1 | 网卡(也称为NIC) |
| 2 | 块设备 |
| 3 | 控制台 |
| 4 | 熵源 |
| 5 | 内存气球(传统) |
| 6 | ioMemory |
| 7 | Rpmsg |
| 8 | SCSI主机 |
| 9 | 9P传输 |
| 10 | Mac80211 WLAN |
| 11 | Rproc串行 |
| 12 | Virtio CAIF |
| 13 | 内存气球 |
| 16 | GPU设备 |
| 17 | 定时器/时钟设备 |
| 18 | 输入设备 |
| 19 | 套接字设备 |
| 20 | 加密设备 |
| 21 | 信号分配模块 |
| 22 | pstore设备 |
| 23 | IOMMU设备 |
| 24 | 内存设备 |
Virtio PCI设备遵循PCI标准规范,使用PCI标准配置空间和I/O区域。Virtio设备的PCI供应商ID为0x1AF4,PCI设备ID范围从0x1000到0x107F,其中0x1000 - 0x103F用于传统(virtio0.95)设备,0x1040 - 0x107F用于现代(virtio1.0)设备。
2. **设备状态设置**:
- 如果客户机操作系统将设备状态设置为Acknowledge,则设备被识别。
- 如果设置为Driver,则找到合适的驱动程序。
3. **设备驱动程序的安装和配置**:包括前端和后端使用特征位进行协商、虚拟队列的初始化、可选的MSI - X安装和特定于设备的配置等。
4. **设置设备状态为Driver_OK**:如果过程中出现错误,则状态设置为Failed。
### 2.3 关键参数详解
#### 2.3.1 设备状态
- **传统设备**:定义了五种状态,分别为:
- 0:驱动程序写入“0”表示设备需要重启。
- 1:“Acknowledge”表示客户机操作系统已找到有效的Virtio设备。
- 2:“Driver”表示客户机操作系统已找到合适的驱动程序(如Virtio网卡驱动程序)。
- 4:“Driver_OK”表示驱动程序已成功安装,设备可使用。
- 128:“FAILED”表示驱动程序安装过程中出现错误。
- **现代设备**:在传统设备状态基础上增加了两种状态:
- 8:“FEATURES_OK”表示驱动程序和设备功能已成功协商。
- 64:“DEVICE_NEEDS_RESET”表示设备出现故障,需要重启。
#### 2.3.2 特征位
设备(后端)和驱动程序(前端)都有各自的特征位。现代设备的特征位支持64位,传统设备仅支持32位。设备和驱动程序都可以通过特征位提供自身支持的功能集。在初始化过程中,驱动程序读取设备的特征位,然后选择自身能够支持的特征作为驱动程序支持的功能,从而完成驱动程序和设备之间的特征协商。具体特征位如下:
- 0 - 23:特定设备的特征位,每个设备都有自己的特征定义。例如,virtio - net设备支持24种特征,其中VIRTIO_NET_F_CSUM使用位0表示是否支持主机端的校验和卸载,VIRTIO_NET_F_GUEST_CSUM使用位1表示是否支持客户机端的校验和卸载。大多数网卡支持校验和卸载,如果数据包目的地不在当前系统内,客户机可以将校验和计算推迟到主机网卡。
- 24 - 38:保留用于队列和特征协商机制的扩展。例如,VIRTIO_F_RING_INDIRECT_DESC使用位28表示驱动程序是否支持间接描述符表,这对于进行更大数据传输是必要的。
- 39及以上:保留用于未来扩展(仅适用于现代设备)。
#### 2.3.3 中断配置
现代和传统设备都支持两种中断源(设备中断和队列中断)和两种中断模式(INTx和MSI - X)。每个设备只有一个设备中断源,每个队列有一个队列中断源。中断的具体数量还取决于中断模式:
- **INTx模式**:一个设备仅支持一个中断,因此设备中断源和队列中断源必须共享此中断。
- **MSI - X模式**:支持多个中断,每个单独的中断称为一个中断向量。假设有n个队列,则设备中有n个队列中断加上一个设备中断,总共n + 1个中断,这些中断可以灵活配置,任何一个中断源都可以配置和使用任何一个中断向量。
目前INTx模式很少使用,新系统通常支持更强大的MSI - X模式。启用MSI - X中断后,传统设备可以使用MSI - X附加配置中的两个寄存器,将设备和队列中断映射到相应的MSI - X中断向量(对应配置向量和队列向量)。这两个寄存器为16位,可读可写。通过写入有效的中断向量值(有效值范围:0x0 - 0x7FF)来映射中断,发生中断后,设备或队列将通过此中断向量通知驱动程序。写入VIRTIO_MSI_NO_VECTOR(0xFFFF)将关闭中断并取消映射,读取这两个寄存器将返回指定中断源到中断向量的映射,如果没有映射,则返回VIRTIO_MSI_NO_VECTOR。在现代设备中,这两个寄存器直接包含在通用配置中,使用方式与传统设备类似。
#### 2.3.4 特定于设备的配置
此配置空间包含特定于设备的信息。以网卡设备为例,传统设备可以定义MAC地址和状态信息,现代设备可以添加更多信息,如最大队列数,这种机制提供了功能扩展和灵活性。
## 3.
0
0
复制全文


