在前面”virtio-blk浅析”一文中我们看到了virtio-blk设备的整体架构,其核心和virtio-net设备一样通过将针对磁盘操作的request命令放入virtqueue的vring中进行传输,由于要通过用户态程序的Qemu周转一次,再到host kernel层,性能有一定的损耗。为提升virtio-blk的性能,出现了两种方案。
- Bio-based virtio-blk
- vhost-blk
下面我们来看下这两种加速方案。
在前面”virtio-blk浅析”一文中我们看到了virtio-blk设备的整体架构,其核心和virtio-net设备一样通过将针对磁盘操作的request命令放入virtqueue的vring中进行传输,由于要通过用户态程序的Qemu周转一次,再到host kernel层,性能有一定的损耗。为提升virtio-blk的性能,出现了两种方案。
下面我们来看下这两种加速方案。
在前面的文章中在介绍virtio机制中,可以看到在通常的应用中一般使用QEMU用户态程序来模拟I/O访问,而Guest中的数据要通过Guest到Host Userspace的第一次拷贝,再经过Host userspace的第二次拷贝,这种多次的数据拷贝和CPU特权级的切换对性能有相当大的影响。为加速virtio设备的I/O性能,VHOST通过driver的形式在Host Kernel中直接实现了virtio设备的模拟。通过在Host Kernel中对virtios设备的模拟运行允许Guest与Host Kernel直接进行数据交换,从而避免了用户空间的system call与数据拷贝的性能消耗。
在前面几文中已经大体介绍了virtio的重要组成,包括virtio net设备的创建,vring的创建,与virtio设备的交互方式,我们就从网络数据包的发送角度来看下virtio的具体使用流程。
KVM上设备I/O虚拟化的性能问题长期存在,此时由Rusty Russell开发的virtio引起了开发者们的注意并逐渐被KVM等虚拟化平台接纳并作为了其I/O虚拟化最主要的一个通用框架。
Virtio使用virtqueue来实现其I/O机制,每个virtqueue就是一个承载大量数据的queue。vring是virtqueue的具体实现方式。
Qemu为virtio设备分配了专门的pci设备ID,device IDs (vendor ID 0x1AF4) from 0x1000 through 0x10FF,而pci子系统中的厂商ID和设备ID就成为了virtio类型和厂商域的组成,所以PCI驱动是不需要知道virtio设备类型的真正含义,对于Kernel来说只是注册了一个struct virtio_device,并挂载到了virtio bus类型总线上,并由virtio driver来驱动。
virtio设备对于Linux Kernel中的设备类型来说是作为pci设备被使用的,因此具有pci设备的所有属性,所以其也具备了PCI配置空间。