在KVM虚拟化的架构里,对CPU的虚拟化采用的是硬件辅助的方式(Intel VT-x,AMD-V),效率比较高,内存的虚拟化有Intel EPT技术的支持,效率也没有问题;那么对于像磁盘驱动器,网卡等io设备来说,KVM提供两种虚拟化方式:采用全虚拟化纯软件实现的QEMU/KVM方式,采用半虚拟化的virtio方式。

如上图,在一些桌面虚拟化产品里,默认采用的是QEMU/KVM方式对磁盘,网卡设备进行虚拟化

对于大多数采用开源KVM方案的桌面虚拟化产品来说,通过在客户机操作系统里安装增强工具,可以将io设备的虚拟化方式改成virtio,从而增强性能

下面分别介绍下这两种虚拟化方式的实现原理:

(一)利用QEMU来模拟IO设备

QEMU以纯软件的方式来模拟IO设备的运行

当客户机的设备驱动程序发起IO请求时,内核KVM模块会截获这次请求,然后经过翻译将本次请求放到内存里的IO共享页面,并通知客户机QEMU模拟进程(客户虚拟机也是底层Linux系统里的一个用户空间进程QEMU-KVM,这是KVM里很重要的一个概念)来处理本次请求,这里KVM模块起的是一个传达的作用,传统的在物理机上运行的程序好比你在餐厅里吃饭,你直接通过服务员(驱动)告诉厨师(硬件)你要吃什么菜,而虚拟化环境里就像在网上叫外卖,你无需知道餐厅在哪,你(客户虚拟机)只需要通知外卖平台(KVM模块)你要吃某个菜(执行一次IO操作),剩下的事情就是由外卖平台去与具体的餐厅协调,保证按时将外卖送到你手上。

从技术的角度来说,内核KVM模块是一个进程,QEMU模拟程序也是一个进程,IO请求的翻译和传达实际上是进行了一次进程间通信(IPC),而实现方式是由KVM模块将拦截的请求放到内存里的IO共享页,共享内存(shared memory)正是IPC最快的实现方式,当一个进程写共享内存,其他进程都立即知道写入的内容,而且可以访问。

QEMU模拟程序获知了本次IO操作的具体信息后,交由硬件模拟代码(Emulation Code)来执行本次IO操作,通过Linux内核里的物理硬件驱动,来调用物理IO设备完成IO操作,并返回所期望得到的值,再将这个值放回IO共享页,通知KVM模块读取这个值,并转交给客户虚拟机上的IO设备驱动。

通过QEMU模拟IO设备,优点是可以模拟出各种各样的硬件,包括一些老的,不常用的设备,兼容性比较广泛,而且不用修改客户机操作系统,就可以让模拟设备在客户机上正常工作。但缺点也很大,每次IO路径太长,大量进程间通信有可能带来的阻塞(虽然阻塞不分配CPU时间片,但也要进行线程的挂起和唤醒),而且所有的IO指令都是敏感指令也是特权指令(Ring1),也会带来VMExit,VMEntry的开销,且IO返还值的传递也要进行多次数据复制,故性能较差。

(二)VirtIO半虚拟化IO设备

VirtIO是运行在Hypervisor上的一个抽象的API接口,通过让客户机知道自己运行在虚拟化环境里,进而根据virtio标准与Hypervisor进行协作,从而获得更好的IO性能。

其基本结构如下图

其前端驱动frontend是运行在客户虚拟机上的驱动程序模块(也就是我们在桌面上安装的虚拟机增强工具,里面包含了如virtio-blk,virtio-net等驱动),而后端处理程序backend是在QEMU里实现的,这种类似于C/S架构的方式屏蔽了底层设备驱动之间的差异,虚拟机中的virtio驱动与QEMU之间通过标准化接口进行通信,不需要经过复杂的翻译转换(而是类似一个中国人和一个日本人,都用对方能懂的语言比如英语沟通,大家一起去完成某个任务),所以效率较高。

在前后端驱动之间,还定义了两层数据结构来对通信进行处理,其中virtio这一层是虚拟队列接口(队列最大的特点是FIFO,先提交的请求先执行),每个虚拟机都有自己的虚拟队列,这也是IO虚拟化和CPU虚拟化之间的区别,没有时间片的分配,所有虚拟机的io请求抢占现有资源,至于怎么对IO做Qos控制,还在学习中,不敢妄言,各个厂家的实现方式似乎并不相同,以后有机会再总结。从逻辑上看,虚拟队列接口就是连接前端驱动和后端处理程序的通道,一个前端驱动可以同时使用若干个虚拟队列,比如对virtio-net网络驱动同时使用2个虚拟队列(一个用于发送,一个用于接受),而virtio-blk块设备驱动只需要使用一个虚拟队列。virtio的下层是virtio-ring的数据结构,这是一个环形缓冲区(又叫循环队列,也是队列的一种),作用是保存前端驱动的多次请求,再批量交给后端驱动处理,同时防止队列溢出(循环队列的特点),通过这种设计约定实现批量处理而不用对客户机的每个io请求进行一次处理,大大提高了客户机与Hypervisor层的协作效率。

virtio的半虚拟化驱动方式,有很高的io性能,几乎和直接跑在硬件上一样,因此只要可能,使用virtio是高效的选择,不过其缺点是需要更改客户机的操作系统,使之知道自己跑在虚拟化环境里(在一些桌面虚拟化产品里,是通过在客户机系统里安装虚拟化增强工具来实现的),同时要求客户虚拟机和宿主机的Linux内核都支持virtio(好比之前的例子里,中国人和日本人都得懂英文,不然还是得等翻译),目前在比较新的Linux(内核版本2.6.24及以上)都支持virtio,所以长远看通过virtio进行io设备的虚拟化是必然。

KVM中的网络IO设备虚拟化方式相关推荐

  1. Neutron中的网络I/O虚拟化(by quqi99)

    作者:张华  发表于:2014-04-03 版权声明:可以任意转载,转载时请务必以超链接形式标明文章原始出处和作者信息及本版权声明 (http://blog.csdn.net/quqi99 ) 我的实 ...

  2. select 实现类似多线程_redis中的网络IO有了解过吗,它是单线程的还是多线程的,为什么要用单线程?...

    redis 采用网络IO多路复用技术来保证在多连接的时候,系统的高吞吐量. 多路-指的是多个socket连接,复用-指的是复用一个线程.多路复用主要有三种技术:select,poll,epoll.ep ...

  3. java中io.nio.aio_Java中网络IO的实现方式-BIO、NIO、AIO

    在网络编程中,接触到最多的就是利用Socket进行网络通信开发.在Java中主要是以下三种实现方式BIO.NIO.AIO. 关于这三个概念的辨析以前一直都是好像懂,但是表达的不是很清楚,下面做个总结完 ...

  4. KVM中Virtio网络的演化之路

    作为一个开放的标准接口,virtio一直在云计算与虚拟化中扮演着重要的角色.而virtio网络接口,作为virtio标准支持下最复杂的接口之一,在虚拟机/容器网络加速.混合云加速中一直扮演着重要角色. ...

  5. Java中9种IO的读取方式

    数据的读写,按照数据类型可以分为两种:字符流和字节流(二者区别?).所以数据读取方式按照数据类型也可以分为两类:字节流的读取和字符流的读取. 一.字节流读取操作: |  | |-----1.FileI ...

  6. java 摄像头访问_image – 在Java中访问网络摄像头的最佳方式

    我需要使用Java访问网络摄像头.这是我想做的 >访问网络摄像头 >现在用户可以看到网络摄像头工作,因为他的脸在屏幕上可见 (已经听到一些libs有没有显示webcam的视频输出) > ...

  7. KVM中Windows网络重置常用指令

    因为新配置的IP和DNS可能还没有生效,可以使用刷新dns命令使DNS配置生效 ipconfig /flushdns 其它网络重置常用指令如下: 查看网络状态       netstat 跟踪路由信息 ...

  8. KVM中I/O设备直接分配和SR-IOV(十六)

    学习 KVM 的系列文章: 本文将分析 PCI/PCIe 设备直接分配(Pass-through)和 SR-IOV, 以及三种 I/O 虚拟化方式的比较. 1. PCI/PCI-E 设备直接分配给虚机 ...

  9. KVM 介绍之CPU和内存虚拟化

    学习 KVM 的系列文章:  (1)介绍和安装 (2)CPU 和 内存虚拟化 (3)I/O QEMU 全虚拟化和准虚拟化(Para-virtulizaiton) (4)I/O PCI/PCIe设备直接 ...

最新文章

  1. 解决Python报错UnicodeDecodeError: 'gbk' codec can't decode byte 0x80 in position 658: illegal multibyte
  2. Javascript 中 apply、call、bind
  3. 计算机应用属不属于科技股,哪些股票属于科技股
  4. 获取一组radio按钮选中的值Value
  5. 测试工程师需要具备的技能
  6. java兔子问题编程思路详解_Java算法之“兔子问题”
  7. Spring 的动态数据源实现
  8. 无人机会飞丢及编程上的改进思路
  9. 文档计算机无法分页,word文档总是重新分页 word文档老是分页显示怎么解决
  10. 分号的html文本,html分号
  11. Python Tkinter——数字拼图游戏详解版
  12. python基础数据类型
  13. 震惊!!!郑州市一程序员在上班时趁着公司没人竟然在看......
  14. css中的before与after
  15. 一个良好的习惯由二十八天养成。
  16. Annotation-specified bean name 'brandController' for bean class [com.qingcheng.controller.goods.Bran
  17. orecal 锁表了
  18. 产品精益画布 Lean Canvas
  19. 使用免驱动版的usb无线网卡,怎么把台式机设置成热点
  20. 【python】在图片加上数字

热门文章

  1. 一、CentOS7启动U盘制作
  2. PDF文件页码拆分方法
  3. PLSQL Developer-模板(Template) 使用教程
  4. 爱心代码李峋同款爱心 python html
  5. python画图基础
  6. MCU多功能遥测终端机RTU的特点和应用知多少?
  7. linux如何查看有几个网卡,linux 查看有几块网卡
  8. 2023年系统集成项目管理工程师通关攻略
  9. qt designer 建qrc文件供Eric6使用步骤
  10. IPC 进程间通讯,排队输出--day33