DPDK原理探索: igb_uio
我们知道,DPDK的核心特性在于绕开内核对网卡设备进行操作,而要实现这一点,DPDK采用的是Linux内核提供的UIO框架,并且对其进行封装,最终暴露给用户的东西就是——igb_uio
。
0.0 什么是igb_uio
?
igb_uio
本质上是一个驱动(driver)
。它是以一个内核模块的形式被加入到内核中的。我们使用的insmod
命令其实就是一个插入内核模块(kernel module)
的工具。
igb_uio
的初始化:
模块初始化
可以看到,igb_uio
的初始化是通过igbuio_pci_init_module
来实现的,而这个函数又是怎么被调用的呢?事实上,在igb_uio
内核模块被插入时,就会触发上图中module_init
所设置的初始化回调函数。
igb_uio初始化回调函数
在igbuio_pci_init_module
函数中,我们关心的是pci_register_driver
函数,该函数将igbuio_pci_driver
向内核中进行注册。同时,在igbuio_pci_driver
结构体中,还有一个id_table
的字段,它是一个struct pci_device_id
数组,表示当前驱动所管理的所有设备。在pci_register_driver
函数中,会调用probe
回调函数去探测所有设备。但特殊的是,igb_uio
在初始化时是没有管理任何设备的,即id_table
数组为空。
奇怪了,显然igb_uio
的驱动是需要管理网卡设备的,但是我们这里又没有任何驱动可以被探测到,那我们的网卡设备是什么时候被加入到igb_uio
驱动的管理中的呢?
答案就是DPDK提供的usertools/dpdk-devbind.py
脚本,这个脚本可以将某个网卡设备绑定为igb_uio
驱动下的网卡设备,而绑定之后,就可以触发probe
回调函数探测这个新的网卡设备,探测成功后,我们的新网卡就进入了igb_uio
的设备数组中。
1.0igb_uio
的设备探测过程:
在igbuio_pci_probe
函数中, 完成的主要工作有五个:
- 使能当前设备,即通过
pci_enable_device(dev)
函数enable
当前设备 igbuio_setup_bars
,该函数的功能是将当前设备的所有PCI BAR
的全部信息读取到struct uio_info
结构体中,后续注册UIO
设备时需要使用- 设置
DMA
模式 - 初始化
UIO
设备的File Operations
,即open
、release
和irqcontrol
等 - 通过
uio_register_device
函数将当前设备注册为UIO
设备。
1.1 PCI BAR
设备信息的读取:
事实上,一个PCI
设备通常有6个PCI BAR
,这些PCI BAR
在内核中被称为resource
。而每一个PCI BAR
都有各自的类型和物理地址。其中,类型有两种,一种是Memory
类型的资源,另一种是I/O Port
。
PCI BAR的数据读取
其中,对于IORESOURCE_MEM类型,通过igbuio_pci_setup_iomem
函数进行读取,而对于IORESOURCE_IO类型,通过igbuio_pci_setup_ioport
来进行读取。
那么,到底是什么PCI BAR
呢?BAR
的全称是Base Address Register
,它是一个存储基地址的寄存器。在PCI设备内部的内存布局是这样的:
PCI内存布局
而每个BAR
的数据分布如下:
每一个PCI BAR的数据分布
学习地址: Dpdk/网络协议栈/vpp/OvS/DDos/NFV/虚拟化/高性能专家-学习视频教程-腾讯课堂
更多DPDK相关学习资料有需要的可以自行报名学习,免费订阅,久学习,或点击这里加qun免费
领取,关注我持续更新哦! !
1.1.0 igbuio_pci_setup_iomem
的过程:
在igbuio_pci_setup_iomem
函数中,通过pci_resource_start
内核函数可以获取当前PCI BAR
的物理地址起点,而通过pci_resource_len
可以获取当前PCI BAR
的物理地址长度。
IORESOURCE_MEM类型的PCI BAR
在上图中,最后方框标注的部分,就是将我们所读取到的PCI BAR
的数据存入struct uio_info
结构体中,以供后面注册UIO
设备时使用。
值得一提的是,internal_addr
其实在DPDK中是没有用到的,它表示当前PCI BAR
的物理地址映射到内核中的虚拟地址。
1.1.1 igbuio_pci_setup_ioport
的过程:
igbuio_pci_setup_ioport
函数的过程与igbuio_pci_setup_iomem
大致相同。
IORESOURCE_IO
1.1.2 为什么有I/O Memory
和I/O Port
两种类型?
对于一个设备来说,除了自带的内存之外,还可能有寄存器等存储手段。显然,设备自带的内存就属于I/O Memory
,而寄存器等其他的存储手段属于I/O Port
类型。
I/O Space 和 Memory Space
2.0 igb_uio
如何绕开内核?
事实上,所有UIO
设备在sysfs
文件系统下都有一系列的文件接口,而用户程序就可以通过这些文件读取所需的设备信息,例如我们关心的PCI BAR
等。得到了PCI BAR
里存储的设备物理地址,就可以建立内存映射,进而与设备进行通信。
但是在DPDK的PMD中,并未使用PCI BAR
的信息建立内存映射,而是直接使用mmap
,直接映射/dev/uioX
文件从而与某个UIO
设备建立联系。
而不同的PCI BAR
对应的内存区域在mmap
时如何区分呢? 简单地说,可以通过计算偏移量来区分,第n个PCI BAR
对应的内存偏移量为n * pagesz
,即每个PCI BAR
对应的内存区域都在不同的页内。
参考资料:
- DPDK-IGB_UIO
- Userspace I/O HOWTO
- How to Write Linux PCI Driver
- PCI - OSDev Wiki
- Linux Driver Development, Edition 3, by Jonathan Corbet, Alessandro Rubini, and Greg Kroah-Hartman
原文链接:https://zhuanlan.zhihu.com/p/483868843
DPDK原理探索: igb_uio相关推荐
- [App探索]JSBox中幽灵触发器的实现原理探索
前言 幽灵触发器是钟颖大神的JSBox中的一个功能,在app进程被杀死的情况下,也可以将通知固定在通知栏,即便用户点击清除,也能马上再弹出,永远不消失,除非用户关闭App的通知权限或者卸载App,才可 ...
- [App探索]JSBox中幽灵触发器的实现原理探索 1
建了一个面试题解答的项目,大家可以看一看,希望大家帮忙给一个star,谢谢了! 项目地址:https://github.com/NotFound9/interviewGuide 前言 幽灵触发器是钟颖 ...
- Next.js性能优化之ISR渲染入门和原理探索
前言 术语说明: SSR -- 服务端渲染 SSG -- 静态生成 ISR -- 增量静态化 Date Fetch 函数 -- 本文特指服务端数据获取的几种函数 getStaticProps . ge ...
- webpack 热加载原理探索
前言 在使用 dora 作为本地 server 开发一个 React 组件的时候,默认使用了 hmr 插件.每次修改代码后页面直接更新,不需要手动 F5 ,感觉非常惊艳,这体验一旦用上后再也回不去了. ...
- DPDK igb/ixgbe/igb_uio bind ubind,网卡解绑
igb是千兆网卡 ixgbe是万兆网卡 igb_uio 是DPDK用户层网卡驱动 一般电脑的文件 安装DPDK的文件 这个绑定和解除绑定的命令 查看网卡的指令是 dpdk tool是里面的 ./dpd ...
- dpdk 20.02 igb_uio.ko 编译
dpdk从20.02版本以后默认不编译igb_uio.ko 更改config/common_base的 CONFIG_RTE_EAL_IGB_UIO=y 可以实现编译.
- dpdk编译安装igb_uio报错 insmod: ERROR: could not insert module igb_uio.ko: File exists 问题
前言 出错问题:insmod: ERROR: could not insert module igb_uio.ko: File exists 什么时候出现 insmod build/kmod/igb_ ...
- kind富文本编辑器_富文本编辑器原理探索
经常在做企业网站的管理系统的时候需要用到富文本编辑器,之前基本上都是直接去 npm 或者 github 上面搜找一些排名考前或者 readme 写的好的库,直接拿来用.万变不离其宗,是时候探索下本质了 ...
- AAAI 2019 | 借鉴传染病学原理探索医学图像CNN可解释性
机器之心发布 作者:牛钰浩.谷林(共同一作), 陆峰(通讯作者) 等 虽然深度学习在医疗图像的病变检测上取得了巨大成功,然而,现有的方法几乎都将 CNN 作为黑盒使用,没有进一步揭示做出分类的依据. ...
最新文章
- linux shell 查看 cpu核数
- from torch._C import * ImportError: DLL load failed: 找不到指定的模块。
- 宏定义和Typedef区别?
- python生成静态库_使用boost.python静态库
- linux 执行sh_linux下执行脚本 sh -x XXX.sh 调试中存在大量/r 的问题
- ant vue 离线文档_超全离线开发手册
- Mr.J-- jQuery学习笔记(九)--事件绑定移除冒泡
- 给文件夹中的文件批量更改名称
- OpenShift 4 - 通过 REST API 操作 OpenShift
- 贝叶斯分析——从数值积分到MCMC
- Scikit-learn:聚类clustering
- pdf2docx:Python实现PDF转Word
- Vue实例常用的4个选项
- 5G即将全面普及,我们到底该换手机卡还是换手机?
- pecl 安装redis
- 中国历史和世界史横向对照表,收藏了长知识。 ​​​​
- 通过Nginx访问静态页面
- invalidate()和postInvalidate() 的区别及使用
- 2019计算机调剂武汉大学,2019年武汉大学考研调剂相关规定
- 洛谷P1827 [USACO3.4] 美国血统 American Heritage
热门文章
- cdce62005配置说明
- 桌面快捷方式不见了怎么办实际解决
- 2022-2027年中国女性向游戏行业发展监测及投资战略研究报告
- wpa_supplicant的控制接口简单说明
- dns被自动修改_【每日一技】iPhone网速慢怎么办?教你配置DNS让网速飞起
- 旺旺老师JavaSE基础第一章(06)Java编译器(上)
- android wear悦跑圈,悦跑圈下载_悦跑圈app最新v3.2.1下载_游戏吧
- SitePoint Podcast#190:Dave Rupert的开源项目
- 程序汪8万接的共享口罩项目,开发周期1个月
- 【Kotlin基础系列】第6章 包与导入