【原创】Linux虚拟化KVM-Qemu分析(九)之virtio设备

背景

  • Read the fucking source code! –By 鲁迅
  • A picture is worth a thousand words. –By 高尔基

说明:

  1. KVM版本:5.9.1
  2. QEMU版本:5.0.0
  3. 工具:Source Insight 3.5, Visio
  4. 文章同步在博客园: https://www.cnblogs.com/LoyenWang/

新的一年, 大家牛起来!
祝小姐姐们:
落雁沉鱼 兰质蕙心 明眸皓齿 螓首蛾眉 天生丽质 天香国色 杏脸桃腮 煦色韶光 涎玉沫珠 宜嗔宜喜 远山芙蓉 艳色绝世 余霞成绮 阿娇金屋 逞娇呈美 国色天香 花颜月貌 绝色佳人 暗香盈袖 闭月羞花 倾国倾城 温婉娴淑 千娇百媚 仪态万千…

祝男的:
新年好。

  1. 概述

先来张图:

【原创】Linux虚拟化KVM-Qemu分析(九)之virtio设备
  • 图中罗列了四个关键模块: Virtio DeviceVirtio DriverVirtqueueNotification(eventfd/irqfd)
  • Virtio Driver:前端部分,处理用户请求,并将I/O请求转移到后端;
  • Virtio Device:后端部分,由Qemu来实现,接收前端的I/O请求,并通过物理设备进行I/O操作;
  • Virtqueue:中间层部分,用于数据的传输;
  • Notification:交互方式,用于异步事件的通知;

想在一篇文章中写完这四个模块,有点 too yong too simple,所以,看起来又是一个系列文章了。
本文先从Qemu侧的virtio device入手,我会选择从一个实际的设备来阐述,没错,还是上篇文章中提到的网络设备。

  1. 流程分析

在Qemu的网卡虚拟化时,通常会创建一个虚拟网卡前端和虚拟网卡后端,如下图:

【原创】Linux虚拟化KVM-Qemu分析(九)之virtio设备
  • 在虚拟机创建的时候指定参数: -netdev tap, id = tap0, -device virtio-net-pci, netdev=tap0
  • 创建一个 Tap网卡后端设备;
  • 创建一个 Virtio-Net网卡前端设备;
  • 网卡前端设备和后端设备进行交互,最终与Host的驱动完成数据的收发;

全文围绕着 Tap设备的创建和 Virtio-Net设备的创建展开。

入口流程如下:

【原创】Linux虚拟化KVM-Qemu分析(九)之virtio设备
  • Qemu的代码阅读起来还是比较费劲的,各种盘根错节,里边充斥着面向对象的思想,先给自己挖个坑,后续会专题研究的, this is for you, you have my words.;
  • 图中与本文相关的有三个模块:1)模块初始化;2)网络设备初始化;3)设备初始化;
  • Qemu中设备模拟通过 type_init先编译进系统,在 module_call_init时进行回调,比如图中的 xxx_register_types,在这些函数中都是根据 TypeInfo类型信息来创建具体的实现信息;
  • net_init_client用来创建网络设备,比如 Tap设备;
  • device_init_func根据Qemu命令的传入参数创建虚拟设备,比如 Virtio-Net

下边进入细节, the devil is in the details

  1. tap创建

从上文中,我们知道, TapVirtio-Net属于前后端的关系,最终是通过结构体分别指向对方,如下图:

【原创】Linux虚拟化KVM-Qemu分析(九)之virtio设备
  • NetClientState是网卡模拟的核心结构,表示网络设备中的几个端点,两个端点通过 peer指向对方;

创建Tap设备的主要工作就是创建一个 NetClientState结构,并添加到 net_clients链表中:

【原创】Linux虚拟化KVM-Qemu分析(九)之virtio设备

函数的调用细节如下图:

【原创】Linux虚拟化KVM-Qemu分析(九)之virtio设备
  • 处理流程只关注了核心的处理流程,整个过程有很多关于传入参数的处理,选择性忽略了;
  • net_tap_init:与Host的 tun驱动进行交互,其实质就是打开该设备文件,并进行相应的配置等;
  • net_tap_fd_init:根据 net_tap_info结构,创建 NetClientState,并进行相关设置,这里边 net_tap_info结构体中的接收函数指针用于实际的数据传输处理;
  • tap_read_poll用于将fd添加到Qemu的AioContext中,用于异步响应,当有数据来临时,捕获事件并进行处理;

以上就是Tap后端的创建过程,下文将针对前端创建了。

  1. virtio-net创建

这是一个复杂的流程。

4.1 数据结构

Qemu中用C语言实现了面向对象的模型,用于对设备进行抽象,精妙!
针对Virtio-Net设备,结构体及拓扑组织关系如下图:

【原创】Linux虚拟化KVM-Qemu分析(九)之virtio设备
  • DeviceState作为所有设备的父类,其中派生了 VirtIODevicePCIDevice,而本文研究的 Virtio-Net派生自 VirtIODevice
  • Qemu中会虚拟一个PCI总线,同时创建 virtio-net-pcivirtio-balloon-pcivirtio-scsi-pci等PCI代理设备,这些代理设备挂载在PCI总线上,同时会创建Virtio总线,用于挂载最终的设备,比如 VirtIONet
  • PCI代理设备就是一个纽带;

4.2 流程分析

与设备创建相关的三个函数,可以从 device_init_func入口跟踪得知:

【原创】Linux虚拟化KVM-Qemu分析(九)之virtio设备
  • 当Qemu命令通过 -device传入参数时, device_init_func会根据参数去查找设备,并最终调用到该设备对应的类初始化函数、对象初始化函数、以及realize函数;
  • 所以,我们的分析就是这三个入口;

4.2.1 class_init

【原创】Linux虚拟化KVM-Qemu分析(九)之virtio设备
  • 在网卡虚拟化过程中,参数只需要指定PCI代理设备即可,也就是 -device virtio-net-pci, netdev=tap0,从而会调用到 virtio_net_pci_class_init函数;
  • 由于实现了类的继承关系,在子类初始化之前,需要先调用父类的实现,图中也表明了继承关系以及调用函数顺序;
  • C语言实现继承,也就是将父对象放置在自己结构体的开始位置,图中的颜色能看出来;

4.2.2 instance_init

类初始化结束后,开始对象的创建:

【原创】Linux虚拟化KVM-Qemu分析(九)之virtio设备
  • 针对 Virtio-Net-PCI的实例化比较简单,作为代理,负责将它的后继对象初始化,也就是本文的前端设备 Virtio-Net

4.2.3 realize

【原创】Linux虚拟化KVM-Qemu分析(九)之virtio设备
  • realize的调用,比较绕,简单来说,它的类继承关系中存在多个 realize的函数指针,最终会从父类开始执行,一直调用到子类,而这些函数指针的初始化在什么时候做的呢?没错,就是在class_init类初始化的时候,进行了赋值,细节不表,结论可靠;
  • 最终的调用关系就如图了;

到目前为止,我们似乎都还没有看到 Virtio-Net设备的相关操作,不用着急,已经很接近真相了:

【原创】Linux虚拟化KVM-Qemu分析(九)之virtio设备
  • virtio_net_pci_realize函数,会触发 virtio_device_realize的调用,该函数是一个通用的virtio设备实现函数,所有的virtio设备都会调用,而我们的前端设备 Virtio-Net也是virtio设备;
  • virtio_net_device_realize就到了我们的主角了,它进行了virtio通用的设置(后续在数据通信中再分析),还创建了一个 NetClientState端点,与 Tap设备对应,分别指向了对方,惺惺相惜,各自安好;
  • virtio_bus_device_plugged表示设备插入总线时的处理,完成的工作就是按照PCI总线规划,配置各类信息,以便与Guest OS中的virtio驱动交互,后续的文章再分析了;

本文基本捋清了虚拟网卡前端设备和后端设备的创建过程,完成的工作只是绑定了彼此,数据交互以及通知机制,留给后续吧。

参考

《 Virtual I/O Device (VIRTIO) Version 1.1》
https://www.redhat.com/en/blog/virtio-devices-and-drivers-overview-headjack-and-phone

欢迎关注个人公众号,不定期更新技术文章。

【原创】Linux虚拟化KVM-Qemu分析(九)之virtio设备

Original: https://www.cnblogs.com/LoyenWang/p/14399642.html
Author: LoyenWang
Title: 【原创】Linux虚拟化KVM-Qemu分析(九)之virtio设备

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/585937/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • MySQL-连接数据库

    连接数据库在操作数据库之前,需要连接它,输入命令:mysql -u用户名 -p密码。 在你自己本机上连接数据库用上述方式是可以的,不过在平台上连接数据库还需要加上一句-h127.0…

    Linux 2023年6月8日
    097
  • 软件工程 统一过程软件(RUP) 第5篇随笔

    1.RUP简介 本质: 是”一般的过程框架” 为软件开发,进行不同抽象层之间”映射”,安排其开发活动的次序,指定任务和需要开发的志平…

    Linux 2023年6月7日
    0123
  • RabbitMQ超详细安装教程(Linux)

    镜像下载、域名解析、时间同步请点击阿里云开源镜像站 1、简介 官网:https://www.rabbitmq.com/ RabbitMQ是一个开源的遵循AMQP协议实现的基于Erl…

    Linux 2023年5月27日
    0170
  • 记一次vcenter连接esxi失败问题排查(443端口不通)

    vecenter错误 esxi宿主机重启后,vcenter连接esxi提示超时,使用vmware客户端连接esxi也提示超时,开始介入排查。 故障排查 如何进入命令终端 运行alt…

    Linux 2023年6月14日
    078
  • Docker基础知识

    Docker 是什么 Docker 经常被提起的特点: Docker 技术的基础: Docker 组件: Docker 安装 Docker 常见命令 容器相关操作 获取容器相关信息…

    Linux 2023年6月7日
    0108
  • 什么是可调CAP策略?为什么需要可调CAP策略?

    在说可调CAP策略之前,我们要先说说CAP理论。 CAP理论是设计分布式系统必用的黄金法则,它提出了设计分布式系统的三个基本要求:一致性(Consistency)、可用性(Avai…

    Linux 2023年6月6日
    0117
  • 华为ensp网络拓扑图使用MSTP、OSPF、DHCP、端口聚合以及PPP(CHAP认证)

    404. 抱歉,您访问的资源不存在。 可能是网址有误,或者对应的内容被删除,或者处于私有状态。 代码改变世界,联系邮箱 contact@cnblogs.com 园子的商业化努力-困…

    Linux 2023年6月7日
    0102
  • C++类型转换

    static_cast 相近类型之间的类型 reinterpret_cast 不相近类型之间的类型 const_cast 去掉对象const属性的转换 dynamic_cast 规…

    Linux 2023年6月13日
    098
  • DNS

    DNS是域名系统(Domain Name System),简单来说就是平时上网输入的URL,如 www.baidu.com 就是域名,而DNS就是将这个域名解析成IP地址,如 ww…

    Linux 2023年6月7日
    082
  • ThinkPHP 使用 think-queue 实现 redis 消息队列

    简单介绍:消息队列中间件是大型系统中的重要组件,已经逐渐成为企业系统内部通信的核心手段。它具有松耦合、异步消息、流量削峰、可靠投递、广播、流量控制、最终一致性等一系列功能,已经成为…

    Linux 2023年5月28日
    097
  • [ Skill ] 如何获取库中的 top cell

    https://www.cnblogs.com/yeungchie/ top cell 的一个特点就是没有被其他的单元所调用,下面举例获取某个库中的 top cell。 1. 获取…

    Linux 2023年6月7日
    0101
  • linux 系统调优相关参数

    posted @2022-09-05 00:32 LB_运维技术 阅读(4 ) 评论() 编辑 Original: https://www.cnblogs.com/libin-li…

    Linux 2023年6月13日
    0118
  • Linux快速入门(八)效率工具(SSH)

    (1)Kali(源主机),IP:10.211.55.4/24(2)Ubuntu(目标主机),IP:10.211.55.5/24 OpenSSH用于在远程系统上安全的运行 Shell…

    Linux 2023年6月6日
    090
  • Linux 最小安装与 Xshell 远程工具的使用

    写在前面:本篇文章介绍了CtenOS的最小安装方法,以及使虚拟机使用VMware的桥接模式的方法。桥接模式下的虚拟机,相当于和物理机处于同一物理网络(网线、WIFI等)下。在多台物…

    Linux 2023年6月8日
    0114
  • 剑指offer计划31(数学困难)—java

    1.1、题目1 剑指 Offer 14- II. 剪绳子 II 1.2、解法 刚刚好结束了,这个专题,国庆休息,后面再改 1.3、代码 class Solution { publi…

    Linux 2023年6月11日
    099
  • tomcat服务器和servlet的基本认识

    今天下午在知乎看见了一个老哥的文章,写的是servlet写的很好,以前我对Javaweb方面的理解比较混乱今天看了这位老哥的文章后受益匪浅,知乎名叫:bravo1988​ 里面也有…

    Linux 2023年6月6日
    0109
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球