共计 2217 个字符,预计需要花费 6 分钟才能阅读完成。
本篇文章为大家展示了 qemu Virtio 设备该如何创建,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。
一、什么是 Virtio?
qemu 设备虚拟机化的 roadmap 可以概括为全虚拟化 – 半虚拟化 (又可以分为用户空间和内核空间) – 设备穿透 (又可以分为完整设备穿透和单根虚拟化)。所有的这些演进都是为了提升虚拟设备的性能。
Virtio 则是属于一种半虚拟化解决方案,它是一种前后端架构,虚拟机内部需要安装特定的 virtio 设备驱动作为前端,模拟的设备作为后端,后端可以放在用户空间模拟,也可以放在内核空间模拟。放在内核空间模拟就是 vhost 的实现,如 DPDK,SPDK 等。
Virtio 代理的好处就是特定的设备驱动前后端通过 virtqueue 进行通信,virtqueue 就是一块前后端共享的 memory。从而前后端之间的通信通过对共享 memory 的读写就可以了,相比较全虚拟机化,每次的读写虚拟设备都需要做 vm exit 和 vm entry,通信的代价变小了。
Virtio 带来的不便就是需要开发特定的 virtio 设备驱动,虚拟机需要安装设备驱动。
二、Virtio balloon 设备创建流程
这里分析了 virtio balloon 设备的创建流程,从 qemu 指定参数 -device xxx 设备开始到设备最终的实例化过程。
qemu 中设备对象的实现采用了 QOM 模型,模拟了面向对象语言中的封装、继承和多态。遵循该框架可以很方便的开发新的设备。下图展示了类之间的继承关系。这里比较特别的一点是每一个 virtio 设备都会有一个伴生的 PCI 设备,叫做 virtio PCI 代理设备。该设备主要的作用是实现设备总线相关的功能,而设备类只需要关注设备具体功能的实现。
virtio balloon 设备的创建过程如下:
1. 在 main 函数中会遍历指定的 -device 参数,然后调用 device_init_func 来做设备的初始化。
2. 会依次调用 device_init_func- qdev_device_add – object_new – object_initialize_with_type。主要的初始化工作都是在 object_initialize_with_type 中完成的。
3. 首先会调用 type_initialize 完成类的初始化。在类的初始化中会设置类的 realize 回调函数为 virtio_balloon_pci_realize。该函数在做类对象的实例化的时候会调用。
4. 之后会调用 object_init_with_type 做类对象的初始化。会递归从父对象开始执行 instance_init。TYPE_DEVICE 的 instance_init 函数为 device_initfn。该函数调用执行了 object_property_add_bool 增加了三个属性。其中 realized 属性是当设置了对象真正创建的时候调用的。其 set 回调函数设置为 device_set_realized。任何一个设备创建的时候都会调用该函数。
5. 设备类和对象实例初始化完成后会回到 qdev_device_add 函数,接下来就会进行具体的设备实现过程。
6. 调用 object_property_set_bool 将 realized 属性设置为 true,从而会调用刚才设置的回调函数 device_set_realized。
7. 会首先调用 DeviceClass 的 realize 函数即 virtio_pci_dc_realize。该函数是在 virtio_pci_class_init 中设置的。
8. 父类的 realize 函数会一次调用子类的 realize 函数。接着会调用 PCIDeviceClass 的 realize 函数即 pci_qdev_realize。
9. 然后依次调用 VirtioPCIClass、VirtioBalloonPCIClass 的 realize 函数。从而实现了 VirtioBalloonPCI 设备的创建。最后还需要创建 VirtioBalloon 设备,将其挂载到 PCI 总线上。
10. 即依次调用 VirtioDeviceClass、VirtioBalloonDeviceClass 的 realize 函数。VirtioBalloon 设备的具体实现就是在函数 virtio_balloon_device_realize 中。
整个流程如下图所示,类之间的调用流则如类继承关系图中红线所示。
在 virtio_balloon_device_realize 中,调用 virtio_add_queue 为设备添加了三个 virtqueue。其中两个的回调处理函数为 virtio_ballon_handle_output,另一个是 virtio_balloon_receive_stats。从而构建了从设备的输入输出通道,以及当收到输入输出信息时调用的回调处理函数。
至此设备创建完成,但是还差最后一步将设备挂载到 virtio 总线上去。该步骤是在函数 virtio_device_realize 中实现的。该函数调用 vdc- realize 创建了具体设备后,会调用 virtio_bus_device_plugged,该函数的作用就是将 virtio 设备插入到 virtio 总线。
上述内容就是 qemu Virtio 设备该如何创建,你们学到知识或技能了吗?如果还想学到更多技能或者丰富自己的知识储备,欢迎关注丸趣 TV 行业资讯频道。