QEMU源码全解析 —— virtio(1)

2023-12-11 22:52
文章标签 源码 解析 qemu virtio

本文主要是介绍QEMU源码全解析 —— virtio(1),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

接前一篇文章:

本文内容参考:

《趣谈Linux操作系统》 —— 刘超,极客时间

《QEMU/KVM》源码解析与应用 —— 李强,机械工业出版社

特此致谢!

virtio简介

对于一台虚拟机而言,除了要虚拟化CPU和内存,当然也要虚拟化外部设备,这其中最为典型和关键的是存储和网络。那么这些外部设备应该如何虚拟化呢?

  • 全虚拟化

当然,一种方式(方案)还是完全虚拟化。使用QEMU完全模拟设备,比如,有什么样的硬盘或网卡设备,就使用QEMU模拟一个一模一样的软件的硬盘和网卡设备。这样在虚拟机里边的操作系统看来,使用这些设备和使用物理设备是一样的。传统的设备模拟中,虚拟机内部设备驱动完全不知道自己处在虚拟化环境中。对于网络和存储等,I/O操作会走完整的“虚拟机内核栈 -> QEMU -> 宿主机内核栈”。虽然在这种方式下,做到了完全而真正的虚拟化,但QEMU又充当了翻译官的角色,每个指令都需要与翻译,在此过程(“虚拟机内核栈 -> QEMU -> 宿主机内核栈”)中,会产生很多的VM Exit和VM Entry,性能很差,实在是太慢了。

  • 半虚拟化

另一种方式(方案)是半虚拟化虚拟机里边的操作系统不是一个通用的操作系统,它知道自己是运行在虚拟机里边的也清楚使用的硬盘和网络等设备都是虚拟的,应该加载特殊的驱动才能运行。这些特殊的驱动往往要通过虚拟机里外配合工作的模式,来加速对于物理存储设备和网络设备(等)的使用。而本段的主角——virtio就是采用的此种方式。

virtio方案是旨在提高性能的一种优化方案,在该方案中,虚拟机能够感知到自己处于虚拟化环境,并且会加载相应的virtio总线驱动和virtio设备驱动。

virtio基本原理

在虚拟化技术的早期,不同的虚拟化技术会针对不同硬盘(物理存储)和网络等设备实现不同的驱动。虚拟机里边的操作系统也要根据不同的虚拟化技术及物理存储和网络设备,选择加载不同的驱动。但是,由于硬盘设备和网络设备太多了,驱动纷繁芜杂。

后来就慢慢形成了一定的标准,这就是virtio。顾名思义,virtio就是virtual io的缩写,也即虚拟化I/O设备的意思。virtio负责对于虚拟机提供统一的接口。也就是说,在虚拟机里边的操作系统加载的驱动,以后都统一加载virtio就可以了。

半虚拟化的基本原理如下图所示:

上图主要包括两部分内容:一个是VMM创建出模拟的设备;另一个是操作系统内部安装好该模拟设备的驱动,这个驱动和设备之间使用对应的接口进行通信。

以e1000网卡为例,在传统的全虚拟化方式下,虚拟机内核中的网卡驱动还是与具体的硬件设备相同,也就是说QEMU模拟的是e1000的网卡。虚拟机操作系统还是通过传统的方式进行包的收发。e1000以及其它模拟设备网卡的驱动在收发包的时候,会有很多次的写网卡寄存器或者IO端口的操作,这会导致VM Exit,使得网卡的性能比较差(与上边提到的一致)。

而在半虚拟化环境下,设备和驱动都是新的、专门用来适应虚拟化环境的。虚拟机中的设备驱动与QEMU中的虚拟网卡设备定义一套自己的协议进行数据传输,通过自己约定的接口,可以很方便地进行通信。

virtio即是这样一种利用半虚拟化技术提供I/O性能的框架。virtio框架如下图所示:

virtio是一种前后端架构,包括前端驱动(Front-End Driver)后端设备(Back-End Device)以及自身定义的传输协议。通过传输协议,virtio不仅可以用于QEMU/KVM方案,也可以用于其它的虚拟化方案。如虚拟机可以不必是QEMU,而也可以是其它类型的虚拟机;后端不一定要在QEMU中实现,也可以在内核中实现(这实际上就是vhost方案)。

接下来对以上三个组件做简单介绍:

  • 前端驱动

前端驱动为虚拟机内部的virtio模拟设备对应的驱动每一种前端设备都需要有对应的驱动才能正常运行。前端驱动的主要作用是:1)接收用户态的请求;2)然后按照传输协议将这些请求进行封装;3)再写I/O端口;4)发送一个通知到QEMU的后端设备。

  • 后端设备

后端设备则是在QEMU中,用来接收前端驱动发过来的I/O请求,然后从接收的数据中按照传输协议的格式进行解析。对于网卡等需要实际物理设备交互的请求,后端驱动会对物理设备进行操作,从而完成请求,并且会通过中断机制通知前端驱动。

  • virtio队列

virtio前端和后端驱动的数据传输通过virtio队列(virtio queue,virtqueue)完成一个设备会注册若干个virtio队列,每个队列负责处理不同的数据传输。这些队列有的是控制层面的队列、有的是数据层面的队列。virtqueue是通过vring实现的。vring是虚拟机和QEMU之间共享的一段环形缓冲区。当虚拟机需要发送请求到QEMU的时候就准备好数据,将数据描述放到vring中,写一个I/O端口。然后

这篇关于QEMU源码全解析 —— virtio(1)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/482379

相关文章

C语言中自动与强制转换全解析

《C语言中自动与强制转换全解析》在编写C程序时,类型转换是确保数据正确性和一致性的关键环节,无论是隐式转换还是显式转换,都各有特点和应用场景,本文将详细探讨C语言中的类型转换机制,帮助您更好地理解并在... 目录类型转换的重要性自动类型转换(隐式转换)强制类型转换(显式转换)常见错误与注意事项总结与建议类型

MySQL 缓存机制与架构解析(最新推荐)

《MySQL缓存机制与架构解析(最新推荐)》本文详细介绍了MySQL的缓存机制和整体架构,包括一级缓存(InnoDBBufferPool)和二级缓存(QueryCache),文章还探讨了SQL... 目录一、mysql缓存机制概述二、MySQL整体架构三、SQL查询执行全流程四、MySQL 8.0为何移除查

在Rust中要用Struct和Enum组织数据的原因解析

《在Rust中要用Struct和Enum组织数据的原因解析》在Rust中,Struct和Enum是组织数据的核心工具,Struct用于将相关字段封装为单一实体,便于管理和扩展,Enum用于明确定义所有... 目录为什么在Rust中要用Struct和Enum组织数据?一、使用struct组织数据:将相关字段绑

使用Java实现一个解析CURL脚本小工具

《使用Java实现一个解析CURL脚本小工具》文章介绍了如何使用Java实现一个解析CURL脚本的工具,该工具可以将CURL脚本中的Header解析为KVMap结构,获取URL路径、请求类型,解析UR... 目录使用示例实现原理具体实现CurlParserUtilCurlEntityICurlHandler

深入解析Spring TransactionTemplate 高级用法(示例代码)

《深入解析SpringTransactionTemplate高级用法(示例代码)》TransactionTemplate是Spring框架中一个强大的工具,它允许开发者以编程方式控制事务,通过... 目录1. TransactionTemplate 的核心概念2. 核心接口和类3. TransactionT

数据库使用之union、union all、各种join的用法区别解析

《数据库使用之union、unionall、各种join的用法区别解析》:本文主要介绍SQL中的Union和UnionAll的区别,包括去重与否以及使用时的注意事项,还详细解释了Join关键字,... 目录一、Union 和Union All1、区别:2、注意点:3、具体举例二、Join关键字的区别&php

Spring IOC控制反转的实现解析

《SpringIOC控制反转的实现解析》:本文主要介绍SpringIOC控制反转的实现,IOC是Spring的核心思想之一,它通过将对象的创建、依赖注入和生命周期管理交给容器来实现解耦,使开发者... 目录1. IOC的基本概念1.1 什么是IOC1.2 IOC与DI的关系2. IOC的设计目标3. IOC

java中的HashSet与 == 和 equals的区别示例解析

《java中的HashSet与==和equals的区别示例解析》HashSet是Java中基于哈希表实现的集合类,特点包括:元素唯一、无序和可包含null,本文给大家介绍java中的HashSe... 目录什么是HashSetHashSet 的主要特点是HashSet 的常用方法hasSet存储为啥是无序的

Go中sync.Once源码的深度讲解

《Go中sync.Once源码的深度讲解》sync.Once是Go语言标准库中的一个同步原语,用于确保某个操作只执行一次,本文将从源码出发为大家详细介绍一下sync.Once的具体使用,x希望对大家有... 目录概念简单示例源码解读总结概念sync.Once是Go语言标准库中的一个同步原语,用于确保某个操

Linux中shell解析脚本的通配符、元字符、转义符说明

《Linux中shell解析脚本的通配符、元字符、转义符说明》:本文主要介绍shell通配符、元字符、转义符以及shell解析脚本的过程,通配符用于路径扩展,元字符用于多命令分割,转义符用于将特殊... 目录一、linux shell通配符(wildcard)二、shell元字符(特殊字符 Meta)三、s