一、 virtio概述

KVM是必须使用硬件虚拟化辅助技术(如Intel VT-x、AMD-V)的hypervisor,在CPU运行效率方面有硬件支持,其效率是比较高的;在有Intel EPT特性支持的平台上,内存虚拟化的效率也较高。QEMU/KVM提供了全虚拟化环境,可以让客户机不经过任何修改就能运行在KVM环境中。不过,KVM在I/O虚拟化方面,传统的方式是使用QEMU纯软件的方式来模拟I/O设备(如第4章中提到模拟的网卡、磁盘、显卡等等),其效率并不非常高。在KVM中,可以在客户机中使用半虚拟化驱动(Paravirtualized Drivers,PV Drivers)来提高客户机的性能(特别是I/O性能)。目前,KVM中实现半虚拟化驱动的方式是采用了virtio这个Linux上的设备驱动标准框架。

1、QEMU模拟I/O设备的基本原理和优缺点
在这里插入图片描述
QEMU纯软件方式模拟现实世界中的I/O设备的基本过程模型如图所示。

使用QEMU模拟I/O的情况下,当客户机中的设备驱动程序(device driver)发起I/O操作请求之时,KVM模块中的I/O操作捕获代码会拦截这次I/O请求,然后经过处理后将本次I/O请求的信息存放到I/O共享页,并通知用户控件的QEMU程序。QEMU模拟程序获得I/O操作的具体信息之后,交由硬件模拟代码来模拟出本次的I/O操作,完成之后,将结果放回到I/O共享页,并通知KVM模块中的I/O操作捕获代码。最后,由KVM模块中的捕获代码读取I/O共享页中的操作结果,并把结果返回到客户机中。当然,这个操作过程中客户机作为一个QEMU进程在等待I/O时也可能被阻塞。另外,当客户机通过DMA(Direct Memory Access)访问大块I/O之时,QEMU模拟程序将不会把操作结果放到I/O共享页中,而是通过内存映射的方式将结果直接写到客户机的内存中去,然后通过KVM模块告诉客户机DMA操作已经完成。

QEMU模拟I/O设备的方式,其优点是可以通过软件模拟出各种各样的硬件设备,包括一些不常用的或者很老很经典的设备(如RTL8139的网卡),而且它不用修改客户机操作系统,就可以实现模拟设备在客户机中正常工作。在KVM客户机中使用这种方式,对于解决手上没有足够设备的软件开发及调试有非常大的好处。而它的缺点是,每次I/O操作的路径比较长,有较多的VMEntry、VMExit发生,需要多次上下文切换(context switch),也需要多次数据复制,所以它的性能较差。

2、Virtio的基本原理和优缺点

Virtio最初由澳大利亚的一个天才级程序员Rusty Russell编写,是一个在hypervisor之上的抽象API接口,让客户机知道自己运行在虚拟化环境中,从而与hypervisor根据 virtio 标准协作,从而在客户机中达到更好的性能(特别是I/O性能)。目前,有不少虚拟机都采用了virtio半虚拟化驱动来提高性能,如KVM和Lguest。

QEMU/KVM中,Virtio的基本结构框架如图所示
在这里插入图片描述
其中前端驱动(frondend,如virtio-blk、virtio-net等)是在客户机中存在的驱动程序模块,而后端处理程序(backend)是在QEMU中实现的。在这前后端驱动之间,还定义了两层来支持客户机与QEMU之间的通信。其中,“virtio”这一层是虚拟队列接口,它在概念上将前端驱动程序附加到后端处理程序。一个前端驱动程序可以使用0个或多个队列,具体数量取决于需求。例如,virtio-net网络驱动程序使用两个虚拟队列(一个用于接收,另一个用于发送),而virtio-blk块驱动程序仅使用一个虚拟队列。虚拟队列实际上被实现为跨越客户机操作系统和hypervisor的衔接点,但它可以通过任意方式实现,前提是客户机操作系统和virtio后端程序都遵循一定的标准,以相互匹配的方式实现它。而virtio-ring实现了环形缓冲区(ring buffer),用于保存前端驱动和后端处理程序执行的信息,并且它可以一次性保存前端驱动的多次I/O请求,并且交由后端去动去批量处理,最后实际调用宿主机中设备驱动实现物理上的I/O操作,这样做就可以根据约定实现批量处理而不是客户机中每次I/O请求都需要处理一次,从而提高客户机与hypervisor信息交换的效率。

virtio半虚拟化驱动的方式,可以获得很好的I/O性能,其性能几乎可以达到和native(即:非虚拟化环境中的原生系统)差不多的I/O性能。所以,在使用KVM之时,如果宿主机内核和客户机都支持virtio的情况下,一般推荐使用virtio达到更好的性能。当然,virtio的也是有缺点的,它必须要客户机安装特定的Virtio驱动使其知道是运行在虚拟化环境中,且按照Virtio的规定格式进行数据传输,不过客户机中可能有一些老的Linux系统不支持virtio和主流的Windows系统需要安装特定的驱动才支持Virtio。不过,较新的一些Linux发行版(如RHEL 6.3、Fedora 17等)默认都将virtio相关驱动编译为模块,可直接作为客户机使用virtio,而且对于主流Windows系统都有对应的virtio驱动程序可供下载使用。

原文链接: http://smilejay.com/2012/11/virtio-overview/

概而言之, virtio 虚拟化 hypervisor 中位于设备之上的抽象层。 virtio 由 Rusty Russell 开发,他当时的目的是支持自己的 虚拟化 解决方案 lguest。本文在开篇时介绍 虚拟化 和模拟设备,然后探索 virtio 的细节。本文的重点是来自 2.6.30 内核发行版的 virtio 框架。 Linux 是 hypervisor 展台。如我的 剖析 Linux hypervisor 所述,Linux 提供各种 hypervisor 解决方案,这些解决方案都有自己的特点和优点。这
virtio 设备上进行批量数据传输的机制被称为 virtqueue 。每个设备可以拥有零个或多个 virtqueue ,当 Driver 想要向设备发送数据时,它会填充 Descriptor Table 中的一项(或将几项链接在一起),并将描述符索引写入 Available Ring 中,然后它通知 Device ,当 Device 完成后,它将描述符索引写入 Used Ring 中并发送中断。 Virtio 在 Guest 中实现了前端 驱动 ,在 Host (qemu)中实现了后端 驱动 ,前后端之间通
virtio 原理 拿网络 驱动 部分做案例,网络 驱动 virtio -net有两个队列:接收队列和发送队列;每个队列都对应一个virtqueue,两个队列之间是互不影响的。 前后端利用virtqueue的方式如下图所示: 当收包时,ReceiveQueue需要客户机 driver提前填充分配好的空buffer,然后记录到availRing,并在恰当的时机通知后端,当外部网络有数据包到达时,qemu后端就从availRing 中获取一个buffer,然后填充数据,完事后记录buffer head index到use
1, virtio ring(vring)队列由 guest 准备(申请内存),vring包含三部分:desc, avail, used, 且 vring.avail 所指向的 desc 也由 guest 准备,guest 给队列准备 desc 分两种: 1),发送时准备,如 virtio -blk 所用队列以及 virtio -net 中 guest 主动发送数据用到的队列; 2),事先准备好,如 virtio -net 中 host 主动发送数据的队列; 2, virtio -blk ...
一、Vring数据结构 1、数据结构图的左 部分描述了 virtio -blk设备与 virtio 设备的 关系 ,virtqueue与vring_virtqueue的 关系 ,如下: virtio -blk是一个 virtio 设备,它看到的队列是virtqueue,里面没有vring的实现,只记录了vring中还有多少空闲的buffer可以使用 vring_virtqueue是一个virtqueue,它将VRing的实现隐藏在virtqueue下面,当一个 virtio -blk设备真正要发送数据时,只要传入virtqueu
在上一篇文章(网络 虚拟化 ——QEMU虚拟网卡)中,讨论了经典的网络设备全 虚拟化 技术。这种技术不需要guest内核对虚拟网络设备有任何的感知和特殊处理,但性能较差,一次读写操作可能会产生多次需要Hypervisor模拟实现的行为。 为了改善虚拟网络设备的性能,各类Hypervisor都提供了自己的 虚拟化 网络技术。在这种模式下,guest内核中使用的网络设备和 驱动 是为 虚拟化 场景特殊设计和实现的, 驱动 的实现特别适配了Hypervisor的一些特性,尽量减少了需要Hypervisor介入进行模拟实现的指