本文共 1980 字,大约阅读时间需要 6 分钟。
1) 客户机的设备驱动程序发起 I/O 请求操作请求
2) KVM 模块中的 I/O 操作捕获代码拦截这次 I/O 请求
3) KVM经过加工处理后将本次 I/O 请求的信息放到 I/O 共享页 (sharing page),并通知用户空间的 QEMU 程序。
4) QEMU 程序获得 I/O 操作的具体信息之后,交由硬件模拟代码来模拟出本次 I/O 操作。(模拟设备可能会使用物理的设备,或者使用纯软件来模拟。)
5) I/O操作完成之后,QEMU 将结果放回 I/O 共享页,并通知 KMV 模块中的 I/O 操作捕获代码。
6) KVM 模块的捕获代码读取 I/O 共享页中的操作结果,并把结果放回客户机。
当然,这一操作过程中,客户机VM作为QEMU的一个thread(vm_runing)在等待I/O时可能被阻塞(Block)。另外,当客户机通过DMA访问大块内存时,QEMU模拟程序不会把操作结果放到I/O共享页中,而是通过内存映射的方式将结果直接写到客户机的内存中去,然后通过KVM模块告诉客户DMA操作完成)
优点:
1、不用修改客户机操作系统(即不做任何修改,使用原生设备驱动)。
2、可以模拟一些老式经典设备,解决因为手头没有足够设备而引入的调试开发问题。
缺点:
1、I/O路径长,依赖KVM和QEMU来做中间的信息处理。
2、多次进行数据拷贝。
3、虚拟机和宿主机,内核态和用户态多次进行上下文切换(context switch),性能差。
Virtio的出现可以解决上述性能问题。
优势:
1、标准化:Virtio实现统一的设备接口,Virtio以及virtio-ring完成标准传输层队列接口,上层可以对接各种类型设备,如blk、net、pci、scsi等设备。
2、环形队列批量处理I/O请求
3、优化传统方案中内核态与用户态频繁切换,虚拟机和宿主机陷入陷出带来的性能开销。
缺点:
1、前端VM需要加载Virtio驱动。
采用半摸拟技术(这里的半模拟,主要是体现在多了一个virtio前端驱动)后,配合前端驱动,虚拟化设备完全可以采用全新的事件通知和数据传递机制进而大幅提升性能,例如在virtio-blk磁盘中,采用io_event_fd进行前端到后端通知,采用中断注入方式实现后端到前端的通知,并通过IO环(vring)进行数据的共享。
virtio组成结合上图来来看,virtio 可以分为四层,具体包括以下模块:
virtio_blkirtio_netirtio_scsi:前端 guest 中各种设备驱动程序模块。
virtio-pci:virtio设备首先是个PCI设备,会走标准的PCI设备总线模型。
virtio*virtio-ring :virtio主要实现控制面,例如实现虚拟队列接口(数据结构、notify等通信机制),是前后端通信的桥梁,virtio-ring主要偏向数据面,实现两个环形缓冲区,实现了具体的通信机制和数据流。
virtio backend:后端 Hypervisor (实现在Qemu上)上的处理程序模块。
从代码上看,virtio的代码主要分两个部分:QEMU和内核驱动程序。virtio设备的模拟就是通过QEMU完成的,QEMU代码在虚拟机启动之前,为VM创建虚拟设备。虚拟机启动后检测到设备,调用内核的virtio设备驱动程序来加载这个virtio设备
虚拟机的存储由QEMU模拟,可以分为几个部分:
顶层的模拟虚拟机磁盘,这个比如virtio-blk磁盘/virtio-scsi磁盘/ide磁盘,虚拟机往这些磁盘读写数据,QEMU通过顶层磁盘获得虚拟机的IO/SCSI/ATA请求,并转化为具体的磁盘数据读写;
中层的模拟的虚拟机镜像层,比如raw格式/qcow2/sheepdog镜像,其实就是数据以特定协议规则放置,以实现存储的一些高级特性(链接克隆,快照等),数据的扇区排序通过这层,已经和原始的数据不一致;
底层适配host上不同具体存储文件/设备,中层镜像层已经把数据重新排列,数据在底层写入/读取host上真正的文件/设备。
温馨提示:
请识别二维码关注公众号,点击原文链接获取更多云计算、虚拟化和容器等技术资料总结。
转载地址:http://ixgkb.baihongyu.com/