dpdk uio整體分析及網卡加載

參考:https://zhuanlan.zhihu.com/p/477600165

一、Linux內核知識點

1. __attribute__ constructor/destructor  

(1)若函數被設定為constructor屬性,則該函數會在 main()函數執行之前被自動的執行。

(2)若函數被設定為destructor屬性,則該函數會在main()函數執行之后或者exit()被調用后被自動的執行

2.container_of宏

作用是通過結構體內某個成員變量的地址和該變量名,以及結構體類型。找到該結構體變量的地址

3. EXPORT_SYMBOL

標簽內定義的函數或者符號對全部內核代碼公開,不用修改內核代碼就可以在您的內核模塊中直接調用,即使用EXPORT_SYMBOL可以將一個函數以符號的方式導出給其他模塊使用。


4.EXPORT_SYMBOL_GPL


 與EXPORT_SYMBOL類似,_GPL版本的宏定義只能使符號對GPL許可的模塊可用。 符號必須在模塊文件的全局部分導出,不能在函數中導出

5.ATTR

#define DRIVER_ATTR(_name, _mode, _show, _store) \
    struct driver_attribute driver_attr_##_name = __ATTR(_name, _mode, _show, _store)
#define DRIVER_ATTR_RW(_name) \
    struct driver_attribute driver_attr_##_name = __ATTR_RW(_name)
#define DRIVER_ATTR_RO(_name) \
    struct driver_attribute driver_attr_##_name = __ATTR_RO(_name)
#define DRIVER_ATTR_WO(_name) \
    struct driver_attribute driver_attr_##_name = __ATTR_WO(_name)__ATTR定義于文件 include/linux/sysfs.h
#define __ATTR(_name, _mode, _show, _store) {    \.attr = {.name = __stringify(_name), .mode = _mode },  \.show = _show,      \.store = _store,      \
}
說明_name:名稱,也就是將在sys fs中生成的文件名稱。_mode:上述文件的訪問權限,與普通文件相同,UGO的格式,最高權限0644,否則會報錯。_show:顯示函數,cat該文件時,此函數被調用。_store:寫函數,echo內容到該文件時,此函數被調用。

這個主要是綁定網卡時會用到

二、內核UIO驅動框架

內核uio框架通過配置內核選項CONFIG_UIO=y使能Userspace I/O drivers,在內核初始化時會調用uio_init創建uio_class; -----內核uio.c中完成,純內核操作;

//dpdk定義的uio pci設備描述結構
struct rte_uio_pci_dev {struct uio_info info; //uio 通用結構struct pci_dev *pdev;  //pci設備描述結構enum rte_intr_mode mode; //中斷模式
};
struct uio_info {struct uio_device    *uio_dev; //uio設備屬于const char        *name; //名稱const char        *version; //版本號struct uio_mem        mem[MAX_UIO_MAPS];//可映射的內存區域列表,size == 0表示列表結束struct uio_port        port[MAX_UIO_PORT_REGIONS]; //網口區域列表long            irq; //UIO_IRQ_CUSTOM 中斷號unsigned long        irq_flags; //請求中斷號的標志void            *priv;  //可選的私有數據irqreturn_t (*handler)(int irq, struct uio_info *dev_info); //中斷信息處理int (*mmap)(struct uio_info *info, struct vm_area_struct *vma);//內存映射操作int (*open)(struct uio_info *info, struct inode *inode); //打開int (*release)(struct uio_info *info, struct inode *inode); //釋放int (*irqcontrol)(struct uio_info *info, s32 irq_on); //中斷控制操作 關閉/打開 當向/dev/uioX中寫入值時
/*1.注冊uio驅動入口部分
*/
module_init(uio_init)/*2.調用此函數
*/
static int __init uio_init(void)
{return init_uio_class();
}/*3. 真正的注冊部分
*/
static int init_uio_class(void)
{int ret;/* 申請字符設備號(alloc_chrdev_region),分配字符設備(cdev_alloc),uio字符設備操作函數掛載(cdev->ops = &uio_fops;)并將字符設備"uio"注冊到系統中(cdev_add); */ret = uio_major_init();if (ret)goto exit;/*創建“/sys/class/uio”設備目錄或文件系統,此時該目錄為空,在insmod igb_uio.ko后且運行python腳本綁定網卡后此目錄下才有內容;*/ret = class_register(&uio_groups);if (ret) {printk(KERN_ERR "class_register failed for uio\n");goto err_class_register;}return 0;err_class_register:uio_major_cleanup();
exit:return ret;
}/*__class_register函數
*/int __class_register(struct class *cls, struct lock_class_key *key)
{struct subsys_private *cp;int error;pr_debug("device class '%s': registering\n", cls->name);cp = kzalloc(sizeof(*cp), GFP_KERNEL);if (!cp)return -ENOMEM;klist_init(&cp->klist_devices, klist_class_dev_get, klist_class_dev_put);INIT_LIST_HEAD(&cp->interfaces);kset_init(&cp->glue_dirs);__mutex_init(&cp->mutex, "subsys mutex", key);error = kobject_set_name(&cp->subsys.kobj, "%s", cls->name);if (error) {kfree(cp);return error;}/* set the default /sys/dev directory for devices of this class */if (!cls->dev_kobj)cls->dev_kobj = sysfs_dev_char_kobj;#if defined(CONFIG_BLOCK)/* let the block class directory show up in the root of sysfs */if (!sysfs_deprecated || cls != &block_class)cp->subsys.kobj.kset = class_kset;
#elsecp->subsys.kobj.kset = class_kset;
#endifcp->subsys.kobj.ktype = &class_ktype;cp->class = cls;cls->p = cp;error = kset_register(&cp->subsys);if (error) {kfree(cp);return error;}error = class_add_groups(class_get(cls), cls->class_groups);class_put(cls);error = add_class_attrs(class_get(cls));class_put(cls);return error;
}EXPORT_SYMBOL_GPL(__class_register);

三、dpdk中的igb_uio模塊

1.dpdk-steup.sh中插入igb_uid模塊

step2_func()
{TITLE="Setup linux environment"TEXT[1]="Insert IGB UIO module"FUNC[1]="load_igb_uio_module"
}load_igb_uio_module()
{if [ ! -f $RTE_SDK/$RTE_TARGET/kmod/igb_uio.ko ];thenecho "## ERROR: Target does not have the DPDK UIO Kernel Module."echo "       To fix, please try to rebuild target."returnfiremove_igb_uio_module/sbin/lsmod | grep -s uio > /dev/nullif [ $? -ne 0 ] ; thenmodinfo uio > /dev/nullif [ $? -eq 0 ]; thenecho "Loading uio module"sudo /sbin/modprobe uiofifi# UIO may be compiled into kernel, so it may not be an error if it can't# be loaded.echo "Loading DPDK UIO module"//把igb_uio模塊加入到linux內核驅動中,執行insmod igb_ui.losudo /sbin/insmod $RTE_SDK/$RTE_TARGET/kmod/igb_uio.koif [ $? -ne 0 ] ; thenecho "## ERROR: Could not load kmod/igb_uio.ko."quitfi
}

2.igb_uio

注冊igb_uio驅動主要做兩件事情

    第一件事是配置中斷模式;

    第二種是注冊驅動

static struct pci_driver igbuio_pci_driver = {.name = "igb_uio",//id_table指針為空(即deviceid為空,類似內核igb_pci_tbl,dpdk的pci_id_igb_map),找不到驅動能匹配的設備,不會調用.probe鉤子函數初始化;.id_table = NULL,.probe = igbuio_pci_probe,.remove = igbuio_pci_remove,
};//插入驅動到內核
static int __init
igbuio_pci_init_module(void)
{int ret;if (igbuio_kernel_is_locked_down()) {pr_err("Not able to use module, kernel lock down is enabled\n");return -EINVAL;}if (wc_activate != 0)pr_info("wc_activate is set\n");//配置中斷模式ret = igbuio_config_intr_mode(intr_mode);if (ret < 0)return ret;//注冊驅動return pci_register_driver(&igbuio_pci_driver);
}/*1.入口部分
*/
module_init(igbuio_pci_init_module);

pci_register_driver屬于內核中函數,是向pci總線上注冊uio設備驅動

 以下是內核函數

#define pci_register_driver(driver)		\__pci_register_driver(driver, THIS_MODULE, KBUILD_MODNAME)int __pci_register_driver(struct pci_driver *drv, struct module *owner,const char *mod_name)
{/* initialize common driver fields */drv->driver.name = drv->name;drv->driver.bus = &pci_bus_type;drv->driver.owner = owner;drv->driver.mod_name = mod_name;spin_lock_init(&drv->dynids.lock);INIT_LIST_HEAD(&drv->dynids.list);/* register with core */return driver_register(&drv->driver);
}
EXPORT_SYMBOL(__pci_register_driver);int driver_register(struct device_driver *drv)
{int ret;struct device_driver *other;BUG_ON(!drv->bus->p);if ((drv->bus->probe && drv->probe) ||(drv->bus->remove && drv->remove) ||(drv->bus->shutdown && drv->shutdown))printk(KERN_WARNING "Driver '%s' needs updating - please use ""bus_type methods\n", drv->name);other = driver_find(drv->name, drv->bus);if (other) {printk(KERN_ERR "Error: Driver '%s' is already registered, ""aborting...\n", drv->name);return -EBUSY;}ret = bus_add_driver(drv);if (ret)return ret;ret = driver_add_groups(drv, drv->groups);if (ret) {bus_remove_driver(drv);return ret;}kobject_uevent(&drv->p->kobj, KOBJ_ADD);return ret;
}
EXPORT_SYMBOL_GPL(driver_register);int bus_add_driver(struct device_driver *drv)
{struct bus_type *bus;struct driver_private *priv;int error = 0;bus = bus_get(drv->bus);if (!bus)return -EINVAL;pr_debug("bus: '%s': add driver %s\n", bus->name, drv->name);priv = kzalloc(sizeof(*priv), GFP_KERNEL);if (!priv) {error = -ENOMEM;goto out_put_bus;}klist_init(&priv->klist_devices, NULL, NULL);priv->driver = drv;drv->p = priv;priv->kobj.kset = bus->p->drivers_kset;error = kobject_init_and_add(&priv->kobj, &driver_ktype, NULL,"%s", drv->name);if (error)goto out_unregister;klist_add_tail(&priv->knode_bus, &bus->p->klist_drivers);if (drv->bus->p->drivers_autoprobe) {if (driver_allows_async_probing(drv)) {pr_debug("bus: '%s': probing driver %s asynchronously\n",drv->bus->name, drv->name);async_schedule(driver_attach_async, drv);} else {error = driver_attach(drv);if (error)goto out_unregister;}}module_add_driver(drv->owner, drv);error = driver_create_file(drv, &driver_attr_uevent);if (error) {printk(KERN_ERR "%s: uevent attr (%s) failed\n",__func__, drv->name);}error = driver_add_groups(drv, bus->drv_groups);if (error) {/* How the hell do we get out of this pickle? Give up */printk(KERN_ERR "%s: driver_create_groups(%s) failed\n",__func__, drv->name);}if (!drv->suppress_bind_attrs) {error = add_bind_files(drv);if (error) {/* Ditto */printk(KERN_ERR "%s: add_bind_files(%s) failed\n",__func__, drv->name);}}return 0;out_unregister:kobject_put(&priv->kobj);kfree(drv->p);drv->p = NULL;
out_put_bus:bus_put(bus);return error;
}int sysfs_create_groups(struct kobject *kobj,const struct attribute_group **groups)
{int error = 0;int i;if (!groups)return 0;for (i = 0; groups[i]; i++) {error = sysfs_create_group(kobj, groups[i]);if (error) {while (--i >= 0)sysfs_remove_group(kobj, groups[i]);break;}}return error;
}
EXPORT_SYMBOL_GPL(sysfs_create_groups);

流程梳理:

insmod igb_uio.ko-->module_init(igbuio_pci_init_module)-->igbuio_pci_init_module-->pci_register_driver(內核函數)-->__pci_register_driver(內核)-->driver_register(內核)

注:

(1)“/sys/bus/pci/drivers/igb_uio/”下存放的是驅動igb_uio目錄文件;

(2)“/sys/class/uio/uioX”下存放的是uio設備目錄文件,與“/dev/uioX”設備句柄對應

四.綁定網卡到igb_uio模塊

4.1 腳本中的代碼

dpdk.setup.shstep2_func()
{TEXT[7]="Bind Ethernet/Baseband/Crypto device to IGB UIO module"FUNC[7]="bind_devices_to_igb_uio"}bind_devices_to_igb_uio()
{if [ -d /sys/module/igb_uio ]; then${RTE_SDK}/usertools/dpdk-devbind.py --statusecho ""echo -n "Enter PCI address of device to bind to IGB UIO driver: "read PCI_PATH//主要是執行此部分sudo ${RTE_SDK}/usertools/dpdk-devbind.py -b igb_uio $PCI_PATH && echo "OK"elseecho "# Please load the 'igb_uio' kernel module before querying or "echo "# adjusting device bindings"fi
}
#! /usr/bin/env python
# SPDX-License-Identifier: BSD-3-Clause
# Copyright(c) 2010-2014 Intel Corporation
#from __future__ import print_function
import sys
import os
import getopt
import subprocess
from os.path import exists, abspath, dirname, basename# The PCI base class for all devices
network_class = {'Class': '02', 'Vendor': None, 'Device': None,'SVendor': None, 'SDevice': None}
acceleration_class = {'Class': '12', 'Vendor': None, 'Device': None,'SVendor': None, 'SDevice': None}
ifpga_class = {'Class': '12', 'Vendor': '8086', 'Device': '0b30','SVendor': None, 'SDevice': None}
encryption_class = {'Class': '10', 'Vendor': None, 'Device': None,'SVendor': None, 'SDevice': None}
intel_processor_class = {'Class': '0b', 'Vendor': '8086', 'Device': None,'SVendor': None, 'SDevice': None}
cavium_sso = {'Class': '08', 'Vendor': '177d', 'Device': 'a04b,a04d','SVendor': None, 'SDevice': None}
cavium_fpa = {'Class': '08', 'Vendor': '177d', 'Device': 'a053','SVendor': None, 'SDevice': None}
cavium_pkx = {'Class': '08', 'Vendor': '177d', 'Device': 'a0dd,a049','SVendor': None, 'SDevice': None}
cavium_tim = {'Class': '08', 'Vendor': '177d', 'Device': 'a051','SVendor': None, 'SDevice': None}
cavium_zip = {'Class': '12', 'Vendor': '177d', 'Device': 'a037','SVendor': None, 'SDevice': None}
avp_vnic = {'Class': '05', 'Vendor': '1af4', 'Device': '1110','SVendor': None, 'SDevice': None}octeontx2_sso = {'Class': '08', 'Vendor': '177d', 'Device': 'a0f9,a0fa','SVendor': None, 'SDevice': None}
octeontx2_npa = {'Class': '08', 'Vendor': '177d', 'Device': 'a0fb,a0fc','SVendor': None, 'SDevice': None}
octeontx2_dma = {'Class': '08', 'Vendor': '177d', 'Device': 'a081','SVendor': None, 'SDevice': None}intel_ioat_bdw = {'Class': '08', 'Vendor': '8086', 'Device': '6f20,6f21,6f22,6f23,6f24,6f25,6f26,6f27,6f2e,6f2f','SVendor': None, 'SDevice': None}
intel_ioat_skx = {'Class': '08', 'Vendor': '8086', 'Device': '2021','SVendor': None, 'SDevice': None}
intel_ntb_skx = {'Class': '06', 'Vendor': '8086', 'Device': '201c','SVendor': None, 'SDevice': None}network_devices = [network_class, cavium_pkx, avp_vnic, ifpga_class]
baseband_devices = [acceleration_class]
crypto_devices = [encryption_class, intel_processor_class]
eventdev

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/21875.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/21875.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/21875.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

開發和滲透偷懶利器utools

目錄 1.前言 1.1 工具簡介 1.2 核心特性 1.3 使用場景 1.4 安裝與使用 1.4.1 下載&#xff1a; 1.4.2 安裝&#xff1a; 1.4.3 配置&#xff1a; 1.4.4 插件市場&#xff1a; 2.懶狗插件介紹 基本介紹 2.1 數據模擬 2.2 隨機生成虛假數據 2.3 API市場 2.4 Hoppscot…

【十二】圖解mybatis日志模塊之設計模式

圖解mybatis日志模塊之設計模式 概述 最近經常在思考研發工程師初、中、高級工程師以及系統架構師各個級別的工程師有什么區別&#xff0c;隨著年齡增加我們的技術級別也在提升&#xff0c;但是很多人到了高級別反而更加憂慮&#xff0c;因為it行業35歲年齡是個坎這是行業里的共…

一文讀懂數據庫中的DB、DBMS、DBS、DBAS

目前數據庫的應用非常廣泛,幾乎各行各業都在直接或間接地與數據庫打交道,例如網上購物、銀行業務、鐵路購票和酒店住宿等。在實際應用中,數據庫、數據庫管理系統、數據庫系統和數據庫應用系統經常被統稱為數據庫,而實質上這4個概念是不一樣的,它們具有不同的定義和含義。下…

暴力數據結構之排序大雜燴

1. 冒泡排序&#xff1a;O(N^2) 邏輯解析&#xff1a; 冒泡排序并沒有什么實際意義&#xff0c;但是有教學意義&#xff0c;相信大部分小白在學習的初期第一個接觸的排序就是冒泡排序。那么接下來我們了解一下他的底層邏輯&#xff1a; 冒泡排序顧名思義就是將最大&#xff08…

PID——調參的步驟

第一步&#xff1a;確定比例增益P 確定比例增益 P 時&#xff0c;首先去掉 PID 的積分項和微分項&#xff0c;一般是令 Ti0、 Td0&#xff08;具體見PID 的參數設定說明&#xff09;&#xff0c;使PID 為純比例調節。 輸入設定為系統允許的最大值60%~70%&#xff0c;由0逐漸加…

idea項目maven下載依賴報錯

報錯&#xff1a; 1、Failure to find bad.robot:simple-excel:jar:1.0 in https://maven.aliyun.com/repository/public was cached in the local repository, resolution will not be reattempted until the update interval of aliyunmaven has elapsed or updates are forc…

python的while循環與for循環總結

前兩章中&#xff0c;我們跟著海綿寶寶的故事&#xff0c;掌握了 while 循環和 for 循環&#xff0c;這兩種不同的循環模式。while 循環和 for 循環都需要有 循環體 和 縮進&#xff0c;我們來復習一下它倆的語法規則&#xff1a; while 循環與 for 循環辨析 學到這里&#x…

Microsoft Edge TTS引擎實現文字轉語音小工具

Microsoft Edge TTS引擎實現文字轉語音小工具 ? 看了一篇文章關于使用Microsoft Edge TTS引擎進行文本轉語音的介紹。正好單位工作上經常用到音視頻的制作和轉換。但是文字變成音頻一直都是播音員口播實現。現在到了AI時代,各種功能強大的AI大模型已經應用到各個領域,大大提…

Docker鏡像導入導出

Docker鏡像導入導出 相關命令 docker export 容器id > x:/xx/xx.tar ##導出容器快照 docker import - x:/xx/xx.tar ##導入容器快照 docker save 鏡像id > x:/xx/xx.tar ##導出鏡像 docker load < x:/xx/xx.tar ##導入鏡像命令詳解 docker save …

在鯤鵬服務器搭建k8s高可用集群分享

高可用架構 本文采用kubeadm方式搭建k8s高可用集群&#xff0c;k8s高可用集群主要是對apiserver、etcd、controller-manager、scheduler做的高可用&#xff1b;高可用形式只要是為&#xff1a; 1. apiserver利用haproxykeepalived做的負載&#xff0c;多apiserver節點同時工作…

nginx反向代理了解

文章目錄 Nginx反向代理反向代理系統調優Proxy Buffer相關指令 Nginx 具有高性能的http和反向代理的web服務器&#xff0c;同時也是一個pop3/smtp/imap代理服務器&#xff0c;使用c語言編寫 **Web服務器&#xff1a;**也叫網頁服務器&#xff0c;web server&#xff0c;主要功…

易聯眾智慧云膠片平臺,助推醫學影像服務“向云端”

在門診室里,張女士焦急地告訴主治醫師,自己忘了帶CT膠片。“您別急,我用系統查詢一下。”醫生輕點幾下鼠標進入云膠片平臺,只用不到10秒就順利完成了影像調取。“不僅我可以看到,您在手機上也能隨時隨地查閱。”張女士根據提示操作,不僅能調閱自己的影像檔案,連抽血化驗結果都可…

Spring MVC 啟動流程?

在 web.xml 文件中給 Spring MVC 的 Servlet 配置了 load-on-startup&#xff0c;所以程序啟動的時候會初始化 Spring MVC&#xff0c;在 HttpServletBean 中將配置的 contextConfigLocation屬性設置到 Servlet 中&#xff0c;然后在FrameworkServlet 中創建了 WebApplicationC…

[GeoServer系列]Shapefile數據發布

【GeoServer系列】——安裝與發布shapefile數據-CSDN博客 將待發布數據放置指定目錄下 webapps\geoserver\data\data 創建存儲倉庫 新建矢量數據源 發布圖層 設置邊框 設置樣式 使用 方式1 let highRoad new Cesium.WebMapServiceImageryProvider({url: http://local…

blender從視頻中動作捕捉,綁定到人物模型

總共分為3個步驟&#xff1a; 1、從視頻中捕捉動作模型 小K動畫網-AIGC視頻動捕平臺 地址&#xff1a;https://xk.yunbovtb.com/ 需要注冊 生成的FBX文件&#xff0c;不能直接導入到blender中&#xff0c; 方法有2種&#xff1a; 第一種&#xff1a;需要轉換一下&#x…

Spring Cloud學習筆記(Nacos):Nacos持久化(未完成)

這是本人學習的總結&#xff0c;主要學習資料如下 - 馬士兵教育 1、Overview2、單機使用MySQL 1、Overview 我們關閉單機下的Nacos后&#xff0c;再重新啟動會發現之前配置的內容沒有被刪除。這時因為Nacos有內嵌的數據庫derby&#xff0c;會自己持久化。 但是在集群的情況下…

QT6.0以上版本實現實時圖像傳輸

目錄 服務端開啟攝像頭&#xff0c;捕獲存儲圖片TCP圖像傳輸延時函數 客戶端建立連接接收數據和處理緩沖區接收的一些想法 QT借助tcp實現圖像傳輸&#xff0c;達到類似實時監控的目的。 QT到6.0以上后貌似原來的5.0的一些圖像的捕獲的函數都無法使用了&#xff0c;網上好像也沒…

KAN(Kolmogorov-Arnold Network)的理解 3

系列文章目錄 第一部分 KAN的理解——數學背景 第二部分 KAN的理解——網絡結構 第三部分 KAN的實踐——第一個例程 文章目錄 系列文章目錄前言KAN 的第一個例程 get started 前言 這里記錄我對于KAN的探索過程&#xff0c;每次會嘗試理解解釋一部分問題。歡迎大家和我一起討…

百度/迅雷/夸克,網盤免費加速,已破!

哈嘍&#xff0c;各位小伙伴們好&#xff0c;我是給大家帶來各類黑科技與前沿資訊的小武。 之前給大家安利了百度網盤及迅雷的加速方法&#xff0c;詳細方法及獲取參考之前文章&#xff1a; 剛剛&#xff01;度盤、某雷已破&#xff01;速度50M/s&#xff01; 本次主要介紹夸…

Python sorted 用法:深入解析排序函數的奧秘

Python sorted 用法&#xff1a;深入解析排序函數的奧秘 在Python編程中&#xff0c;sorted函數是一個強大的工具&#xff0c;用于對可迭代對象進行排序。然而&#xff0c;它的用法和功能遠不止表面看起來那么簡單。本文將深入剖析sorted函數的四個方面、五個方面、六個方面和…