原文信息

作者:LoyenWang

出处:https://www.cnblogs.com/LoyenWang/

公众号:LoyenWang

版权:本文版权归作者和博客园共有

转载:欢迎转载,但未经作者同意,必须保留此段声明;必须在文章中给出原文连接;否则必究法律责任

背景

  • 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. 概述

先来张图:

  • 图中罗列了四个关键模块: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入手,我会选择从一个实际的设备来阐述,没错,还是上篇文章中提到的网络设备。

2. 流程分析

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

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

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

入口流程如下:

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

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

3. tap创建

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

  • NetClientState是网卡模拟的核心结构,表示网络设备中的几个端点,两个端点通过peer指向对方;

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

函数的调用细节如下图:

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

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

4. virtio-net创建

这是一个复杂的流程。

4.1 数据结构

Qemu中用C语言实现了面向对象的模型,用于对设备进行抽象,精妙!

针对Virtio-Net设备,结构体及拓扑组织关系如下图:

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

4.2 流程分析

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

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

4.2.1 class_init

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

4.2.2 instance_init

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

  • 针对Virtio-Net-PCI的实例化比较简单,作为代理,负责将它的后继对象初始化,也就是本文的前端设备Virtio-Net

4.2.3 realize

  • realize的调用,比较绕,简单来说,它的类继承关系中存在多个realize的函数指针,最终会从父类开始执行,一直调用到子类,而这些函数指针的初始化在什么时候做的呢?没错,就是在class_init类初始化的时候,进行了赋值,细节不表,结论可靠;
  • 最终的调用关系就如图了;

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

  • 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设备的更多相关文章

  1. [转载]Linux 线程实现机制分析

    本文转自http://www.ibm.com/developerworks/cn/linux/kernel/l-thread/ 支持原创.尊重原创,分享知识! 自从多线程编程的概念出现在 Linux ...

  2. KVM/QEMU/qemu-kvm/libvirt 概念全解

    目录 目录 前言 KVM QEMU KVM 与 QEMU qemu-kvm Libvirt Libvirt 在 OpenStack 中的应用 前言 如果是刚开始接触虚拟机技术的话, 对上述的概念肯定会 ...

  3. 【原创】Linux虚拟化KVM-Qemu分析(三)之KVM源码(1)

    背景 Read the fucking source code! --By 鲁迅 A picture is worth a thousand words. --By 高尔基 说明: KVM版本:5.9 ...

  4. Linux虚拟化技术KVM、QEMU与libvirt的关系(转)

    说明:个人理解,KVM是内核虚拟化技术,而内核是不能使用在界面上使用的,那么此时QEMU提供了用户级别的使用界面,相互辅助.当然,单独使用QEMU也是可以实现一整套虚拟机,不过QEMU+KVM基本是标 ...

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

    背景 Read the fucking source code! --By 鲁迅 A picture is worth a thousand words. --By 高尔基 说明: KVM版本:5.9 ...

  6. 关于Linux虚拟化技术KVM的科普 科普三(From OenHan)

    http://oenhan.com/archives,包括<KVM源代码分析1:基本工作原理>.<KVM源代码分析2:虚拟机的创建与运行>.<KVM源代码分析3:CPU虚 ...

  7. 关于Linux虚拟化技术KVM的科普 科普二(KVM虚拟机代码揭秘)

    代码分析文章<KVM虚拟机代码揭秘--QEMU代码结构分析>.<KVM虚拟机代码揭秘--中断虚拟化>.<KVM虚拟机代码揭秘--设备IO虚拟化>.<KVM虚拟 ...

  8. KVM+QEMU虚拟化概念

    概念: KVM,即Kernel-basedvirtual machine,由redhat开发,是一种开源.免费的虚拟化技术.对企业来说,是一种可选的虚拟化解决方案. 定义:基于Linux内核的虚拟机 ...

  9. KVM,QEMU核心分析

    现在的问题是学习虚拟化软件KVM相关实施原则.处理,的源代码的分析总结,,若有不对的地方,希望大家提出. 因为有一些代码结构图或者是架构图上传比較麻烦.所以博文都放在了自己的个人博客上.麻烦大家移步查 ...

  10. 【原创】Linux虚拟化KVM-Qemu分析(一)

    背景 Read the fucking source code! --By 鲁迅 A picture is worth a thousand words. --By 高尔基 说明: KVM版本:5.9 ...

随机推荐

  1. CSS笔记(待完善)

    CSS笔记 css权重 ID(100)> class(10)> element(1) css最高权重 !important 块元素(block) 可以设置宽度和高度,独立成行. h1~h6 ...

  2. ARM Cortex-M4|非常好用的一种串口收发方式

    在这里分享项目中我经常使用的一种串口收发方式:阻塞发送 + 接收中断 +空闲中断 + 环形队列 项目代码地址:www.baidu.com 一.简介 串口发送使用最简单的阻塞发送方式,一般来说都是接收的 ...

  3. 超声波、毫米波、ToF激光雷达——在低功耗场景的应用选型

    前言: 目前主要的测距方式有:光学测距,超声波和微波雷达测距. 光学测距又可以分为:双目,结构光,ToF.微波雷达,在消费类产品中,常见的是波长在毫米级别的毫米波雷达.超声波应用比较多的是在车载倒车雷 ...

  4. vue全家桶进阶之路45:Vue3 Element Plus el_button组件

    在 Vue 3 中,Element Plus 的 ElButton 组件提供了多种按钮类型和属性,可以用于实现不同的交互效果.下面是 ElButton 常用的作用和属性: 作用: 用于在页面上添加交互 ...

  5. es 笔记二之基础查询

    本文首发于公众号:Hunter后端 原文链接:es笔记二之基础查询 这一篇笔记介绍 es 的基础查询. 基础查询包括很多,比如排序,类似数据库 limit 的操作,like 操作,与或非等,对于这些操 ...

  6. 记一次处理挖矿程序引发的postgres 连接超时

    近一段时间内发现自己的服务器总是警告被挖矿,然处理挖矿程序中也引发了许多其他的问题,也从中学到了其他的知识,趁今天未加班梳理一下便于巩固,记录日常 文章目录 一.查找进程 1.使用 ll /proc/ ...

  7. ODOO学习网址推荐

    Odoo官文文档: https://www.odoo.com/zh_cn/page/docs http://www.odoo.com/documentation/8.0/ Odoo中文文档推荐: ht ...

  8. 【jmeter】测试socket接口的简单应用

    一.场景 有一天开发问我,有没有什么工具可以测试socket,tcp,当时有点懵,这种需求还是少见 二.方法 使用Jmeter可以进行相关的测试 三.创建服务端环境 使用python搞个socket服 ...

  9. 02.详解盒子模型&选择器初识

    1.Div盒子 用div做圆 能否优化,去掉div之间的距离?margin属性 用表格做圆 2.CSS样式 总结:需要注意的是行级标签设置宽高不会生效 小练习:使用span标签 3.CSS选择器演示及 ...

  10. 让优惠再续一年!SHPC 老客专享

    最近云筏君经常收到自家小伙伴发来的关于产品活动的关心慰问,掐指一算,哦,原来是一年一度大家喜闻乐见的剁手节(学名"双十一")马上要来了! 大家都知道,云筏家的产品向来主打高性价比, ...