1. 基于virtio的半虚拟化概述
1.1 virtio运行结构
① virtio表示虚拟化IO,用于实现设备半虚拟化,即虚拟机中运行的操作系统需要加载特殊的驱动(e.g. virtio-net)且虚拟机知道自己是虚拟机
相较于基于完全模拟的全虚拟化,基于virtio的半虚拟化可以提升设备访问性能
② 运行在虚拟机中的部分称为前端驱动,负责对虚拟机提供统一的接口
③ 运行在宿主机中的部分称为后端驱动,负责适配不同的物理硬件设备
1.2 virtio架构层次
1.2.1 virtio前端驱动
① 运行在虚拟机中
② 针对不同类型的设备有不同的驱动程序,但是与后端驱动交互的接口都是统一的
③ 本文分析virtio-net模块,源码位于drivers/net/virtio_net.c
1.2.2 virtio层
① virtio层实现虚拟队列接口,作为前后端通信的桥梁
② 不同类型的设备使用的虚拟队列数量不同,比如virtio-net使用两个队列,一个用于接收,另一个用于发送
③ 源码位于drivers/virtio/virtio.c
1.2.3 virtio-ring层
① virtio-ring层是虚拟队列的具体实现
② 源码位于driver/virtio/virtio_ring.c
1.2.4 virtio后端驱动
① 运行在宿主机中
② 实现virtio后端的逻辑,主要是操作硬件设备,比如向内核协议栈发送一个网络包完成虚拟机对于网络的操作
③ 在Qemu + KVM虚拟化环境中,源码位于Qemu源码中(尚未详细分析)。后续将分析seL4中的后端实现
【文章福利】小编在群文件上传了一些个人觉得比较好得学习书籍、视频资料,有需要的可以进群【977878001】领取!!!额外赠送一份价值699的内核资料包(含视频教程、电子书、实战项目及代码)
内核资料直通车:Linux内核源码技术学习路线+视频教程代码资料
学习直通车:Linux内核源码/内存调优/文件系统/进程管理/设备驱动/网络协议栈
2. Linux virtio核心数据结构
2.1 virtio_bus结构
struct bus_type是基于总线驱动模型的公共数据结构,定义新的bus,就是填充该结构。virtio_bus定义在drivers/virtio/virtio.c中,具体如下,
说明1:注册virtio_bus
virtio_bus以core_initcall的方式被注册,该方式注册的启动顺序优先级很高(作为对比,module_init最终对应的是device_initcall),在使用中要注意不同组件的启动顺序
说明2:virtio_dev_match函数
virtio驱动的match涉及到virtio_device_id结构,在virtio_device结构中包含该结构;在virtio_driver中则是包含该驱动支持的virtio_device_id列表
具体的match流程如下,
可见virtio驱动的match函数先匹配device字段,后匹配vendor字段,二者都满足条件时match成功
补充:从virtio_dev_match的流程可以看出,virtio_driver中的id_table必须以id->device = 0结尾,以便结束循环
2.2 virtio_device结构
struct virtio_device定义在include/linux/virtio.h中,具体如下,
重点说明如下4个字段,
2.2.1 struct virtio_device_id id
其中的device成员标识了当前virtio_device的用途