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

本文详细解析virtio框架,包括前端驱动、后端设备及其通信机制。virtio利用半虚拟化技术,通过virtqueue(由vring实现)进行I/O性能优化。前端驱动接收用户请求并封装后通过I/O端口通知QEMU后端设备,后端设备操作物理设备并使用中断机制反馈。virtio架构分为前端驱动、后端设备、virtio层和virtio-ring层,各层功能明确,确保高效的数据传输。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

接前一篇文章:

本文内容参考:

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

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

特此致谢!

上一回对于virtio进行了简介,并说明了其基本原理以及框架。对于virtio框架,再来回顾一下。

virtio框架如下图所示:

virtio是一种利用半虚拟化技术提供I/O性能的框架,其是一种前后端架构,包括前端驱动(Front-End Driver)后端设备(Back-End Device)以及自身定义的传输协议

  • 前端驱动

前端驱动为虚拟机内部的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就能够从vring中读取数据信息,进而从内存中读出数据。QEMU完成请求之后,也将数据结构存放在vring中,前端驱动也就可以从vring中得到数据。

此处也有另外一种观点和视角,将virtio架构分为四层:

  • 前端驱动

首先,在虚拟机里面的virtio前端,针对不同类型的设备有不同的驱动程序,但是接口都是统一的。例如,硬盘就是virtio_blk,网络就是virtio_net。

要点:

1)运行在虚拟机中

2)针对不同类型的设备有不同的驱动程序,但是与后端驱动交互的接口都是统一的

3)在Qemu+KVM虚拟化环境中,源码位于KVM源码(Guest 内核)中

  • 后端设备(后端驱动)

其次,在宿主机的QEMU里边,实现virtio后端的逻辑,主要就是操作硬件的设备。例如,通过写一个物理机硬盘上的文件来完成虚拟机写入硬盘的操作。再如,向内核协议栈发送一个网络包完成虚拟机对于网络的操作。

要点:

1)运行在宿主机中

2)实现virtio后端的逻辑,主要是操作硬件设备。比如向内核协议栈发送一个网络包完成虚拟机对于网络的操作。

3)在Qemu+KVM虚拟化环境中,源码位于Qemu源码中

  • virtio层与virtio-ring层

在virtio的前端和后端之间,有一个通信层,里边包括virtio层和virtio-ring层。virtio这一层实现的是虚拟队列接口,算作前后端通信的桥梁;而virtio-ring则是该桥梁的具体实现。

  • virtio层

要点:

1)virtio层实现虚拟队列接口,作为前后端通信的桥梁

2)不同类型的设备使用的虚拟队列数量不同

3)Linux内核源码/源码位于drivers/virtio/virtio.c中

  • virtio-ring层

要点:

1)virtio-ring层是虚拟队列的具体实现

2)源码位于Linux内核源码/driver/virtio/virtio_ring.c中

virtio使用virtqueue进行前端与后端的高速通信。不同类型的设备队列数目不同。virtio-net使用两个队列,一个用于接收、另一个用于发送;而virtio-blk仅使用一个队列。

如果客户机要向宿主机发送数据,则它会将数据的buffer添加到virtqueue中,然后通过写入寄存器通知宿主机。这样宿主机就可以从virtqueue中收到buffer里边的数据了(与前述机制一个意思:当虚拟机需要发送请求到QEMU的时候就准备好数据,将数据描述放到vring中,写一个I/O端口。然后QEMU就能够从vring中读取数据信息,进而从内存中读出数据。QEMU完成请求之后,也将数据结构存放在vring中,前端驱动也就可以从vring中得到数据)。

欲知后事如何,且看下回分解。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蓝天居士

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值