- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章浅谈Linux设备虚拟化技术的演进之路由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
设备虚拟化技术,一直是云计算领域最重要的基础技术之一。我们在虚拟机里面看到的形形色色的设备,比如:网卡,磁盘,键盘,鼠标等,都离不开这项技术的帮助。这篇文章,我们将从技术演进的角度来谈一谈 Linux 现有的以及即将到来的设备虚拟化技术.
在最早期阶段,设备虚拟化常常和机器模拟器技术,比如:QEMU,绑定在一起。我们可以通过 QEMU 模拟真实设备的所有寄存器布局和操作流程,当 QEMU 虚拟机里面设备驱动需要访问该虚拟设备的寄存器时,这条访问指令会被 trap 到 QEMU,由 QEMU 来进行处理。这样,虚拟机里面的设备驱动在操作该虚拟设备时就像在访问真实的硬件设备一样,设备驱动也不需要任何变更.
通过上述这种 trap-and-emulate 的方式来模拟设备,虽然不需要对真实设备驱动进行变更,但是设备访问过程中,频繁的陷入@amp;陷出带来了严重的性能问题,因此,virtio 这类半虚拟化技术应运而生,并于 2008 年合入 Linux 内核主线.
相较于 trap-and-emulate 这种方式,Virtio 不再拘泥于依赖已有的设备驱动,而是定义了一套全新的专用于虚拟设备的驱动框架。设备驱动清楚自己是在操作虚拟设备,因此,在真正的 I/O 路径上规避了大量可能导致陷入@amp;陷出的 mmio/pio 操作,从而提高了性能。虚机里面的 Virtio 驱动和 QEMU 模拟的 Virtio 设备的数据交互,本质上是一套基于共享内存 + 环形队列的通信机制。核心数据结构(split virtqueue)包括:两个 ringbuffer (avail ring, used ring) 和一个 descriptor table。工作机制类似 DMA,虚机内 virtio 驱动首先会将一个请求在内存中需要传输的散列 buffer 的地址、长度组成一个个描述符写入到 descriptor table 中,然后将这些描述符对应的 descriptor table 上的 index 写入到 avail ring 中,并通过 eventfd 机制通知到宿主机上的 virtio backend。由于这些 ringbuffer、descriptor table 以及散列 buffer 都在共享内存中(虚机本质上是一个用户态进程,因此虚机内存是由用户态申请和分配,并可以 share 给其他进程,如:SPDK,DPDK 等),因此,Virtio Backend 可以直接访问并获取到散列 buffer 的地址、长度,进而直接存取这些散列 buffer。当处理完请求之后,Virtio Backend 将数据填充到相应的 buffer,并将对应的 descriptor table index 写入 used ring 中,并通过 eventfd 机制注入中断通知虚机内 virtio 驱动.
Virtio 技术提出之后,Virtio 设备通常是在 QEMU 里面来进行模拟,数据收发都需要经过 QEMU,再到虚机内部。但逐渐地,开发者们发现,当模拟网卡时,在 QEMU 里面进行数据收发,最终都需要通过系统调用的方式,陷入内核来操作网卡硬件进行实际的数据收发。那么,QEMU 到内核的这次上下文切换以及带来的额外拷贝开销,有没有办法优化呢?
Linux 内核社区最终在 2010 年合入了 vhost 这个技术来进行优化,通过将 virtio 的数据面 offload 到一个内核线程来进行处理,这样 virtio 通信机制从原本的 QEMU 用户态 I/O 线程和虚机驱动(QEMU 用户态 vcpu 线程)通信变成了 vhost 内核 I/O 线程和虚机驱动(QEMU 用户态 vcpu 线程)通信。vhost 内核 I/O 线程拿到数据包之后,直接走内核协议栈和网卡驱动进行处理,从而优化掉了 QEMU 到内核态的额外开销.
随着云计算规模的不断扩大,用户一方面不再满足于 Virtio 这类半虚拟化设备带来的性能体验,另一方面 GPU 这类很难进行 virtio 化的设备应用场景与日俱增。在这种背景下,VFIO 这项技术被提出并在 2012 年合入 Linux 内核主线。VFIO 全称是 Virtual Function I/O,它实际是一个用户态设备驱动框架,相较于更早的 uio 这个用户态设备驱动框架,VFIO 能够有效利用硬件 IOMMU 机制进行安全隔离,从而能够广泛地应用在云计算这类有多租户需求的场景中.
如上图所示,通过 VFIO,QEMU 能够直接将自己虚拟出的一个 PCI 设备和一个物理 PCI 设备的数据链路直接打通,当虚拟机里面的设备驱动访问虚拟 PCI 设备的 bar 空间时,通过 EPT 机制,这次 mmio 访问会被重定向到真实物理设备相应的 bar 空间位置,而不再需要 trap 到 QEMU。这样,虚机驱动就相当于可以以接近零消耗的方式直接访问真实物理设备,性能可以达到最佳。同时,VFIO 驱动利用 IOMMU 实现了设备 DMA 和中断的重映射,一方面起到隔离作用,即某个虚机无法操作 VFIO 直通设备向同一宿主机上的其他虚机发起 DMA 和中断,一方面也保证了设备进行 DMA 时通过给定的虚机物理地址能够直接访问到正确的物理内存.
虽然,VFIO 能够给虚机带来接近物理机的 I/O 性能体验,但该技术仍存在一个缺陷,即不支持热迁移,带 VFIO 设备的虚机将没法像传统带 virtio 设备的虚机那样进行热迁移。这就使得开发者们,又开始探寻新的既能满足性能需求又具备运维灵活性的设备虚拟化技术。2014 年 QEMU 社区合入的 vhost-user 技术就是其中之一,由于 QEMU 和 vhost 的线程模型对 I/O 性能的优化并不友好,而且由每个虚机单独分出线程来处理 I/O 这种方式从系统全局角度来看可能也并不是最优的,因此,vhost-user 提出了一种新的方式,即将 virtio 设备的数据面 offload 到另一个专用进程来处理。这样,由于是专用进程,线程模型不再受传统 QEMU 和 vhost 线程模型制约,可以任意优化,同时,还可以以 1:M 的方式同时处理多个虚机的 I/O 请求,而且相较于 vhost 这种内核线程方式,用户进程在运维方面更加具备灵活性,vhost-user 框架在提出之初,就受到广泛关注,并引申出了 SPDK 和 OVS-DPDK 这类以 polling + 用户态驱动为核心的新的虚机 I/O 服务模型.
VFIO 技术在实际应用场景,除了之前提到的不支持热迁移的问题外,还有一个限制就是一个设备只能透传给一个虚机,无法做到资源共享。SR-IOV 技术从某种程度上能够解决这个问题,即将一个物理 PCI 设备从硬件层面进行资源划分,划分成多个 VF,透传给多个虚机进行使用,但是有很多设备可能并不具备 SR-IOV 能力,因此,Linux 内核社区在 2016 年合入了 VFIO-mdev 这个技术框架,希望提供一个标准的接口来帮助设备驱动实现软件层面的资源切分并能够利用 VFIO 技术透传给虚机.
该技术本质上是在内核实现了一个虚拟设备(Mediated device)总线驱动模型,并在 VFIO 内核框架上进行了扩展,增加了对 mdev 这类虚拟设备的支持(mdev bus driver),从原来只支持从标准的硬件 PCI 设备和硬件 platform 设备获取透传信息,比如:PCI bar 空间,变成了既支持直接从硬件设备获取又可以从 mdev 设备驱动定义的虚拟设备接口来获取。这样,比如,当需要将一个 PCI 设备的 bar 空间作为资源切分的话,通过实现合适的 mdev 设备驱动,就可以将 bar 空间以 4KB(页面大小)为粒度,分别透传给不同虚机使用.
VFIO 和 virtio 这两类技术一直是最主流的设备虚拟化技术。VFIO 能够直接将硬件资源透传给虚机使用,性能最佳,virtio 性能稍逊,但胜在更加灵活。那有没有可能将两者的优势结合起来呢?2020 年被合入 Linux 内核主线的 vDPA 技术框架,就是为了实现这一目标.
vDPA 的全称是 Virtio Data Path Acceleration,它表示一类设备:这类设备的数据面处理是严格遵循 Virtio 协议规范的,即驱动和设备会按照第三节提到的 Virtio 通信流程来进行通信,但控制路径,比如:通信流程里面提到的 ring buffer 和 descriptor table 的内存地址,驱动如何告知设备,设备支持的特性,驱动如何感知,这些都是厂商自定义的,不一定会遵循 Virtio 协议。这样做的好处是,可以降低厂商在实现这类设备时的复杂度.
Linux 内核为了将这类设备应用起来,就提出了 vDPA 这样一个技术框架。这个技术框架本质上和 VFIO-mdev 类似,也实现了一个虚拟设备(vDPA device)总线驱动模型,和 VFIO-mdev 不同的是,通过 vDPA 框架虚拟出来的设备,既可以给虚机使用,又可以直接从宿主机(比如:容器)进行访问。这一切都归功于,vDPA 设备的数据路径是遵循 Virtio 协议规范的,因此,可以直接被宿主机上的 virtio 驱动直接访问。同时,该技术框架对 vhost 内核子系统进行了扩展,赋予了类似 VFIO 技术框架的功能,允许将 vDPA 设备用来进行数据通信的硬件资源(ring buffer, descriptor table,doorbell 寄存器等)透传给虚机使用,这样,虚拟机的 virtio 驱动进行数据通信时,也是直接访问硬件资源,而不再需要通过 vhost、vhost-user 等方式进行处理了。更重要的一点是,由于虚机驱动是原本的 virtio 驱动,因此,当需要支持热迁移时,QEMU 可以灵活切换会软件模拟的方式,来保证热迁移的顺利进行。这样,vDPA 这个设备虚拟化技术框架既保证了最佳性能又保留了 virtio 设备的灵活性,而且还统一了虚机和容器的 I/O 技术栈.
通过上述 vDPA 技术框架,我们基本解决了长期以来设备虚拟化技术在虚机场景下暴露的一些问题,而更重要的是,它将 virtio 技术也带到了容器领域。但这个技术框架还存在一个问题,就是需要硬件设备的支持。回想之前提到的 virtio、vhost、vhost-user,本质上都是软件定义的虚拟设备。那 vDPA 这个技术框架有没有可能也能够使用软件定义的设备呢?VDUSE 这项技术就是用来实现这个目标的,通过 VDUSE,我们可以在一个用户进程实现一个软件定义的 vDPA 设备,并可以通过上述 vDPA 框架接入 virtio 或者 vhost 子系统,供容器或者虚机使用.
该项技术是由我们自主研发并在去年 10 月向 Linux 内核社区正式开源的。现阶段我们的方案已经被合入 Linux 内核主线,将在 Linux 5.15 版本与大家见面。同时,我们也会在 9 月 15 日举办的 KVM Forum 这个虚拟化领域的高端技术论坛会议上进行线上分享.
从服务虚拟机到支持容器,从纯软件模拟到硬件直通再到软硬件结合,Linux 设备虚拟化技术这几十年里一直在朝着极致性能、应用灵活等方向不断演进。随着云原生的浪潮,各大硬件厂商的入局,全新的软硬件结合方式不断涌现,我们相信后续也会有更多精彩技术在等待着我们.
原文地址.:https://mp.weixin.qq.com/s/g1kt0DDJwDk2Lg56R5suKw 。
最后此篇关于浅谈Linux设备虚拟化技术的演进之路的文章就讲到这里了,如果你想了解更多关于浅谈Linux设备虚拟化技术的演进之路的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
原谅那个疯狂的标题... 我试图理解面向对象编程中继承与接口(interface)的概念。所以我试图将它与我已经知道的东西联系起来,这就是 CSS。 在 CSS 中,您可以选择在允许元素“继承”样式的
我有一个 C 函数,它返回一个表示二进制数据的 unsigned char*。我在文档中注意到 SWIG 有一个很好的类型映射来处理二进制数据作为 C 函数的输入,但是当 C 函数返回二进制数据及其无
过去遇到过几次类似的问题,想知道用什么语言(方法)来解决类似的问题(我是J2EE/java开发人员): 问题:在一组可能的单词中,根据给定的规则(假设单词可以是 A 和 X 的组合,并且始终以 X 开
这个问题不太可能帮助任何 future 的访客;它只与一个小地理区域、一个特定时刻或一个非常狭窄的情况相关,而这些情况通常不适用于互联网的全局受众。如需帮助使这个问题更广泛地适用,visit the
如果我们已经开发了自己的ORM框架并且该框架在过去的几年中运行良好,那么为什么我们要为即将到来的软件项目学习和使用全新的.net技术,例如LINQ或Entity Framework或NHibernat
即使听起来很奇怪,我相信每个人在处理具有大量自定义组件的大型应用程序时都遇到过此类问题。某个地方生成了 AV,但应用程序仍在继续执行,稍后会出现错误。我不是在谈论多线程应用程序。只是关于通用的单线程应
我正在设计一个新项目,我正在尝试找出将数据/事件从服务器应用程序推送到客户端应用程序(即 WPF 应用程序)的方法。 我知道的两个是: 发布/订阅(即 NServiceBus) Full Duplex
关闭。这个问题不满足Stack Overflow guidelines .它目前不接受答案。 想改善这个问题吗?更新问题,使其成为 on-topic对于堆栈溢出。 5年前关闭。 Improve thi
这个问题在这里已经有了答案: C# .NET: How to check if we're running on battery? (6 个答案) 关闭 9 年前。 我发现许多 API 可以帮助确定
没有 JQUERY!我有一个下拉列表,用户可以在其中选择日期、月份和年份。我创建以下代码并使用 setFullYear 将这些值传递到变量中。有时我还会向这个变量添加天数,这就是变量 ev_num 的
我有一个控件,我想在表单和打印时以不同的方式绘制它。这是我做的方式: private void printDocument1_PrintPage(object sender, System.Drawi
我正在尝试确定从扫描文档中提取手写数据的最佳方法。 手写数据位于特定的方框区域。我生成了文档的数字版本,因此我知道方框区域的坐标,并且如果需要还可以生成文档的其他变体(即被屏蔽以使字段更容易提取的版本
背景 对于基于音乐的问题,我深表歉意,但细节并没有那么重要。我正在按顺序浏览一个 midi 文件,我正在寻找一种有效的方法来查找数据中的模式以找到称为连音符的东西。见下图: 连音符上方有数字(3 或
经验丰富的 Java 新手,寻求您的智慧: 如果无法确保在对象超出范围时执行某些特定的 block 代码,那么还有哪些其他方法可以提供相同的功能?(看起来 finalize 显然不是那个意思) 一个典
我正在玩一个小的油漆应用程序。我想创建不同的画笔提示(不仅仅是简单的线条)。基本思想是沿着鼠标移动重复(冲压)画笔 Nib 。因为鼠标移动不会为鼠标移动的每个像素分派(dispatch)所需的事件。我
我正在制作时间表应用程序。重要的类是: Period id: int clazz: Clazz SubjectTeacher subject: String teac
关闭。这个问题需要更多 focused .它目前不接受答案。 想要改进这个问题吗? 更新问题,使其只关注一个问题 editing this post . 关闭 4 年前。 Improve this q
我有一个奇怪的任务要解决。我们有一个小型视频窗口(如 300x200 像素,256 色调色板)和 44kHz 2ch 声音在服务器上播放。我们需要将此流视频发送给一些客户端(1,2.. 最多 10 个
我很确定我在这里遗漏了一些东西,因为我对 Shapeless 还很陌生并且我正在学习,但是 Aux 技术实际上什么时候开始需要 ?我看到它是用来暴露一个 type通过将其提升为另一个“同伴”的签名来声
微软有什么理由仍然坚持使用 COM 技术(Office 组件仍然是 COM)……当所有用 COM 完成的事情都可以用 .Net 以更好、更有效的方式完成时 最佳答案 因为它需要一个 长完全重写Offi
我是一名优秀的程序员,十分优秀!