【C语言】InfiniBand 驱动mlx4_ib_init和mlx4_ib_cleanup

news2024/9/29 15:24:41

一、中文讲解

这两个函数是Linux内核模块中对于Mellanox InfiniBand 驱动程序初始化和清理的函数。
mlx4_ib_init()函数是模块初始化函数,使用__init宏标注,表示该函数只在模块加载时运行一次。
函数执行的步骤如下:
1. 通过alloc_ordered_workqueue创建一个有序的工作队列wq。这个队列用于将工作项按顺序排队执行,WQ_MEM_RECLAIM表示如果系统内存紧张,允许回收。
   如果工作队列创建失败,返回-ENOMEM错误码,表示内存不足。
2. 在编译时,如果定义了CONFIG_MLX4_IB_DEBUG_FS,则会调用mlx4_ib_register_debugfs函数注册调试文件系统(debugfs),这有助于查询和操作驱动程序的内部信息。
3. 调用mlx4_ib_mcg_init函数初始化多播组(multi-cast group)的一些资源,如果初始化失败,则跳转到标签clean_wq进行清理。
4. 执行init_dev_assign函数,这个函数虽然没有代码显示,但从名称上看,它可能用于初始化设备或分配相应资源。
5. 注册InfiniBand接口到Mellanox的InfiniBand核心驱动,使用的函数为mlx4_register_interface。如果注册失败,会跳转到标签clean_mcg进行清理。
6. 如果所有初始化步骤都成功,函数返回0,表示初始化成功。
如果在任何一步发生错误,函数会执行清理操作:
- clean_mcg: 清除通过mlx4_ib_mcg_init初始化的多播组资源。
- clean_wq: 销毁之前创建的工作队列wq。
mlx4_ib_cleanup()函数是模块清理函数,使用__exit宏标注,表示这个函数在模块卸载时调用。
函数的步骤如下:
1. 调用mlx4_unregister_interface来注销之前注册的Mellanox InfiniBand接口。
2. 如果CONFIG_MLX4_IB_DEBUG_FS被定义,则调用mlx4_ib_unregister_debugfs注销调试文件系统。
3. 调用mlx4_ib_mcg_destroy销毁在模块初始化时创建的多播组资源。
4. 销毁之前创建的工作队列wq。
5. 释放dev_num_str_bitmap,这个变量可能用于跟踪设备编号的分配,但代码段中没有展示它的分配过程。
module_init(mlx4_ib_init);和module_exit(mlx4_ib_cleanup);是宏定义,它们告诉内核模块初始化和退出时应该调用哪些函数。

在 Linux 驱动开发中,mlx4_ib_interface 是一个 mlx4_interface 类型的结构体,它实现了 InfiniBand (IB) 协议栈接口的特定函数。这个结构定义了几个回调函数,这些函数是由底层的 Mellanox 网络设备驱动(通常是 mlx4_core 驱动)在特定事件发生时被调用的。
这些回调函数包括:
- add - 当新设备被添加时调用(例如,当一个新的网络适配器被系统探测到时)。
- remove - 用于当设备被移除时做清理工作。
- event - 当设备关联的事件发生时被调用,例如链接状态改变、硬件错误等。
- protocol - 指定这个接口支持哪种协议(在此示例中是 MLX4_PROT_IB_IPV6,代表 InfiniBand 协议的 IPv6 over IB 版本)。
- flags - 提供额外的信息标志,本例中使用了 MLX4_INTFF_BONDING 标志,表示支持网络接口绑定(bonding)功能。
这个结构体被注册到低层的 mlx4_core 驱动,它是 Mellanox 网络设备的一个核心驱动,提供了基础硬件抽象层的功能。注册后,它成为 mlx4_core 驱动和高层驱动(本例中的 mlx4_ib)之间沟通的桥梁。
mlx4_ib_interface 被注册的地方是在 mlx4_ib_init() 函数,这通常是作为模块初始化的一部分。当 mlx4_ib_init() 函数成功执行后,mlx4_ib 成为 mlx4_core 驱动感知到的一个客户端。
以下是 mlx4_ib_interface 回调函数被调用的时机:
- mlx4_ib_add -  当注册 mlx4_ib_interface 到 mlx4_core 后,如果 mlx4_core 驱动发现一个新的设备,mlx4_core 将调用 mlx4_ib 的 add 回调函数。
- mlx4_ib_remove - 当一个设备需要被移除,可能是因为硬件被物理移除或是模块正在被卸载,remove 回调函数将被调用。
- mlx4_ib_event - 当 mlx4_core 检测到某个事件发生并需要通知 mlx4_ib 模块时,event 回调函数会被调用。
在 mlx4_core 的代码中,会在适当的位置调用 mlx4_ib_interface 结构体中指定的函数,以便在上述事件发生时,正确地通知 InfiniBand 协议栈进行相关操作。这种设计允许 mlx4_core 驱动与多个协议栈(如以太网和 InfiniBand)独立协作,同时保持模块间的松耦合。

在 Linux 内核中,mlx4_core 驱动发现新设备的过程通常涉及 Linux 的 PCI 子系统。mlx4_core` 驱动是 PCI 驱动的一个实现,它注册了一系列的回调函数来处理特定于 PCI 设备的事件。下面是一个简化的描述,解释了驱动程序如何发现新的 PCI 设备:
1. PCI 设备枚举: 当系统启动时,或当新的设备被添加到系统中时(如通过热插拔),PCI 子系统将识别并枚举所有的 PCI 设备。它创建代表这些设备的数据结构,并读取它们的配置空间来获取诸如供应商ID、设备ID、类别码等信息。
2. 驱动注册: 一个 PCI 驱动程序,比如 mlx4_core,会在加载时调用 pci_register_driver() 函数来注册自己。这个注册过程包括提供一个 pci_driver 类型的结构体,该结构体包含对应的供应商ID和设备ID,以及针对新设备的回调函数,如 .probe。

    static struct pci_driver mlx4_pci_driver = {
        .name = DRV_NAME,
        .id_table = mlx4_pci_table,
        .probe = mlx4_probe,
        .remove = mlx4_remove,
        // ... 其他回调函数
    };

    这里的 mlx4_pci_table 包含了 mlx4_core 驱动支持的设备对应的供应商ID和设备ID列表。mlx4_probe 和 mlx4_remove 是当设备被探测到或移除时要调用的函数。
3. 设备和驱动匹配: 一旦驱动注册了自己,PCI 子系统就会遍历所有的 PCI 设备,尝试找出设备ID和供应商ID与驱动中 id_table 匹配的设备。对于每个匹配的设备,PCI 子系统会调用对应驱动的 .probe 回调函数。
4. 设备初始化 (mlx4_probe): 用于 mlx4_core 驱动的 probe 函数通常名为 mlx4_probe。当一个与 mlx4_pci_table 匹配的 Mellanox 设备被探测到时,mlx4_probe 会被调用。在 mlx4_probe 函数内部,驱动程序会执行必要的初始化步骤,如申请资源、设置设备、注册网络设备接口,如果有 InfiniBand 部分,也会在这个时候注册 mlx4_ib_interface 接口。
5. 接口注册: 注册过程可能涉及调用 mlx4_register_interface() 函数,这是 mlx4_core 提供的接口,允许常见的 Mellanox InfiniBand 和以太网功能扩展。这个注册函数会存储一个指向 mlx4_interface 结构体的指针,使得在交互式事件中,mlx4_core 驱动能够调用必要的回调函数。
通过上述流程,mlx4_core 驱动能够发现新的设备并与相关的协议接口(如 mlx4_ib_interface)进行通信,完成设备初始化和事件通知。

二、中文注释

这段代码是一个Linux内核模块的初始化和清除函数,在kernel-4.9\drivers\infiniband\hw\mlx4\main.c文件中,涉及到Mellanox技术的InfiniBand驱动的mlx4子系统。

// Linux内核模块的初始化函数
static int __init mlx4_ib_init(void)
{
    int err;

    // 为名为"mlx4_ib"的workqueue申请有序工作队列,WQ_MEM_RECLAIM标志表示该工作队列支持内存回收
    wq = alloc_ordered_workqueue("mlx4_ib", WQ_MEM_RECLAIM);
    // 如果工作队列创建失败,则返回内存不足的错误代码
    if (!wq)
        return -ENOMEM;

    // 如果定义了CONFIG_MLX4_IB_DEBUG_FS编译选项,注册调试文件系统
    #ifdef CONFIG_MLX4_IB_DEBUG_FS
    mlx4_ib_register_debugfs();
    #endif

    // 初始化多播组。如果初始化失败,则跳转到clean_wq标签进行清理工作。
    err = mlx4_ib_mcg_init();
    // 如果初始化多播组出错,跳到clean_wq的清理流程
    if (err)
        goto clean_wq;

    // 初始化设备分配相关工作。
    init_dev_assign();

    // 注册接口到mlx4核心。如果注册失败,则跳转到clean_mcg标签进行多播组清理工作
    err = mlx4_register_interface(&mlx4_ib_interface);
    if (err)
        goto clean_mcg;

    // 初始化成功,返回0
    return 0;

clean_mcg:
    // 清理多播组
    mlx4_ib_mcg_destroy();

clean_wq:
    // 销毁之前创建的工作队列
    destroy_workqueue(wq);
    // 返回错误代码
    return err;
}

// Linux内核模块的清除函数,用于在模块卸载时被调用
static void __exit mlx4_ib_cleanup(void)
{
    // 注销mlx4接口
    mlx4_unregister_interface(&mlx4_ib_interface);
    // 如果定义了CONFIG_MLX4_IB_DEBUG_FS编译选项,注销调试文件系统
    #ifdef CONFIG_MLX4_IB_DEBUG_FS
    mlx4_ib_unregister_debugfs();
    #endif
    // 清理多播组
    mlx4_ib_mcg_destroy();
    // 销毁工作队列
    destroy_workqueue(wq);
    // 释放之前分配的设备号位图存储空间
    kfree(dev_num_str_bitmap);
}

// 指定模块加载时调用的初始化函数
module_init(mlx4_ib_init);
// 指定模块卸载时调用的清除函数
module_exit(mlx4_ib_cleanup);

这些函数是驱动模块的生命周期钩子,module_init用于表明模块加载时应当调用的函数,而module_exit用于指定模块卸载时的清理函数。__init和__exit宏在内核模块编译时有特殊含义,它们用于优化模块的初始化和退出代码。__init标记的代码在模块加载后不再需要,可以被丢弃;__exit标记的代码在构建内核为非模块支持时丢弃。

三、Linux内核"接口(interface)"机制

在Linux内核中,通过一种称为"接口(interface)"的机制允许不同的驱动程序之间相互沟通。对于Mellanox设备,这可能涉及到mlx4_core模块和mlx4_ib模块之间的交互,分别对应于以太网(Ethernet)和InfiniBand子系统。
在这个上下文中,一个mlx4_core的实例在被PCI子系统探测到后会进行初始化,并且注册到mlx4_core模块的内部数据结构中。这个注册过程中,mlx4_core会公布一系列对于外部模块(如mlx4_ib InfiniBand实现)可以调用的回调函数。
这些回调函数定义在mlx4_interface结构中,如:

static struct mlx4_interface mlx4_ib_interface = {
    .add = mlx4_ib_add,
    .remove = mlx4_ib_remove,
    .event = mlx4_ib_event,
    .protocol = MLX4_PROT_IB_IPV6,
    .flags = MLX4_INTFF_BONDING
};

核心思想是,这个结构会被注册到mlx4_core模块中。当mlx4_core模块中的一个设备完成基础初始化后,它会通知所有注册了的mlx4_interface实例。通过这种方式,当设备被添加(add)或被移除(remove)时,能够反过来触发mlx4_ib_add或mlx4_ib_remove函数的调用。

在添加(add)事件发生时,Ethernet驱动调用mlx4_ib_add,这个函数会负责为InfiniBand功能初始化必要的资源,如设置队列对、分配内存等。相应地,当移除(remove)事件发生时,会调用mlx4_ib_remove以清理InfiniBand相关的资源。

这种机制不仅仅限于设备的添加和移除,也可用于处理其他类型的事件,例如设备状态改变、错误处理等。最终,这允许不同的驱动模块能够同步设备的状态,并在多协议硬件上提供一致的服务。

在Linux内核中,"接口"是指允许不同组件或驱动程序之间沟通和交互的一种机制。这种机制通常包括一系列的函数指针、数据结构和协议,定义了组件之间的通信方式。以下是一些Linux内核中用于不同驱动程序之间相互沟通的接口机制:
1. 平台设备和驱动注册: 平台驱动和设备使用平台设备结构struct platform_device和平台驱动结构struct platform_driver,这两者都包含指向描述它们如何交互的数据结构的指针。设备通常注册它们自己的资源,如内存区域、DMA和中断。当平台设备注册时,核心代码会为匹配的驱动程序调用probe()函数,此时可以建立接口。
2. 设备模型(Device Model): Linux内核的设备模型是一种抽象层,允许内核代码以统一的方式来处理硬件设备。它定义了设备、驱动程序和总线(bus)之间的关系,并通过结构体和方法来描述它们的关系。例如,每个设备结构struct device可以关联一组用于设备操作的方法。
3. 文件操作接口:字符和块设备驱动程序使用文件操作结构`truct file_operations,该结构包含指向不同操作的函数指针(如open(), read(), write(), ioctl(), 等)。这样,用户空间应用可以通过标准的系统调用来与内核中的设备文件进行交互。
4. 网络层接口:网络设备使用网络设备结构struct net_device,通过这种结构,它们可以注册自己给网络子系统,并提供一系列操作函数,以进行网络数据包的发送和接收。
5. 总线类型: 内核定义了多种总线类型,比如PCI, USB, I2C等。每种总线类型都有自己的一套方法和协议,用于发现设备、匹配驱动程序、配置资源等。
6. 内核模块与符号导出: 如果驱动程序或内核模块需要让其它部分的内核代码使用它们提供的功能,它们可以通过EXPORT_SYMBOL或EXPORT_SYMBOL_GPL宏来导出符号(函数、变量的名字)。
7. 回调函数: 驱动程序与硬件通信时通常需要中断处理,内核提供注册中断处理函数的接口,允许驱动编写自己的中断服务例程。
通常,在专业的环境下,这些接口的使用都遵循严格的编程接口(API)和编程约定(ABI),确保了内核的模块和组件可以正确地与彼此通信。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1485548.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

sklearn.preprocessing.RobustScaler(解释和原理,分位数,四分位差)

提示:sklearn.preprocessing.RobustScaler(解释和原理,分位数,四分位差) 文章目录 [TOC](文章目录) 一、RobustScaler 是什么?二、代码1.代码2.输出结果 总结 提示:以下是本篇文章正文内容&…

计算机网络|Socket

文章目录 Socket并发socket Socket Socket是一种工作在TCP/IP协议栈上的API。 端口用于区分不同应用,IP地址用于区分不同主机。 以下是某一个服务器的socket代码。 其中with是python中的一个语法糖,代表当代码块离开with时,自动对s进行销毁…

[VulnHub靶机渗透] CONNECT THE DOTS

🍬 博主介绍👨‍🎓 博主介绍:大家好,我是 hacker-routing ,很高兴认识大家~ ✨主攻领域:【渗透领域】【应急响应】 【Java】 【VulnHub靶场复现】【面试分析】 🎉点赞➕评论➕收藏 …

miniconda3彻底删除虚拟环境

退出虚拟环境:确保您不在要删除的虚拟环境中。如果在,使用命令 conda deactivate 来退出当前激活的虚拟环境。查看虚拟环境列表:运行命令 conda env list 或 conda info -e 来查看所有存在的虚拟环境及其路径。删除虚拟环境:使用命…

HTTP Cookie 你了解多少?

Cookie是什么? 先给大家举个例子,F12 打开浏览器的页面之后,我们能在 Response Headers 的字段里面看到一个header 叫做 Set-Cookie,如下所示 图中包含的 Set-Cookie 为 Set-Cookie:uuid_tt_dd10_20293537580-1709432565344-232…

Maven(黑马学习笔记)

初识Maven 什么是Maven Maven是Apache旗下的一个开源项目,是一款用于管理和构建java项目的工具。 官网:https://maven.apache.org/ Apache 软件基金会,成立于1999年7月,是目前世界上最大的最受欢迎的开源软件基金会&#xff0…

Sqli-labs靶场第15关详解[Sqli-labs-less-15]自动化注入-SQLmap工具注入

Sqli-labs-Less-15 #自动化注入-SQLmap工具注入 SQLmap用户手册:文档介绍 - sqlmap 用户手册 由于这题是post请求,所以先使用burp进行抓包,然后将数据包存入txt文件中打包 用-r 选择目标txt文件 python sqlmap.py -r data.txt -current-db…

JavaScript之数据类型

系列文章目录 文章目录 系列文章目录前言 前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站,这篇文章男女通用,看懂了就去分享给你的码吧。 数据类型   Java…

2023天津公租房网上登记流程图,注册到信息填写

2023年天津市公共租赁住房网上登记流程图 小编为大家整理了天津市公共租赁住房网上登记流程,从登记到填写信息。 想要体验的朋友请看一下。 申请天津公共租赁住房时拒绝申报家庭情况会怎样? 天津市住房保障家庭在享受住房保障期间,如在应申…

力扣 第 125 场双周赛 解题报告 | 珂学家 | 树形DP + 组合数学

前言 整体评价 T4感觉有简单的方法&#xff0c;无奈树形DP一条路上走到黑了&#xff0c;这场还是有难度的。 T1. 超过阈值的最少操作数 I 思路: 模拟 class Solution {public int minOperations(int[] nums, int k) {return (int)Arrays.stream(nums).filter(x -> x <…

Windows上构建一个和Linux类似的Terminal

preview 目的是在Windows上构建一个和Linux类似的Terminal&#xff0c;让Windows炼丹和Linux一样舒适&#xff0c;同是让Terminal取代Xshell完成远程链接。 预览如下图 在Linux下我们使用zsh和oh-my-zsh结合&#xff0c;Windows下我们使用powershell7和oh-my-posh结合。 前提…

力扣● 1049. 最后一块石头的重量 II ● 494. 目标和 ● 474.一和零

● 1049. 最后一块石头的重量 II 题目要把石头分成两堆&#xff0c;这两堆的重量差值最小。相撞之后剩下的石头重量就最小。其实就是要尽量把石头分为差不多重量的两堆&#xff0c;和昨天的● 416. 分割等和子集相似&#xff0c;这样就转换成了01背包问题。 和416题一样&…

【字符串相加】

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言 字符串相加 方法一&#xff1a; 方法二&#xff1a; 总结 前言 世上有两种耀眼的光芒&#xff0c;一种是正在升起的太阳&#xff0c;一种是正在努力学习编程的…

腾讯云幻兽帕鲁游戏存档迁移教程,本地单人房迁移/四人世界怎么迁移存档?

腾讯云幻兽帕鲁游戏存档迁移的方法主要包括以下几个步骤&#xff1a; 登录轻量云控制台&#xff1a;首先&#xff0c;需要登录到轻量云控制台&#xff0c;这是进行存档迁移的前提条件。在轻量云控制台中&#xff0c;可以找到接收存档的服务器卡片&#xff0c;并点击进入实例详情…

LeetCode 2368.受限条件下可到达节点的数目:搜索 + 哈希表

【LetMeFly】2368.受限条件下可到达节点的数目&#xff1a;搜索 哈希表 力扣题目链接&#xff1a;https://leetcode.cn/problems/reachable-nodes-with-restrictions/ 现有一棵由 n 个节点组成的无向树&#xff0c;节点编号从 0 到 n - 1 &#xff0c;共有 n - 1 条边。 给…

ecmascript 6+(2)

引用数据类型&#xff1a; Object, Array, RegExp, Date等 包装类型&#xff1a;&#xff08;底层数据类型会将简单数据类型包装为对象&#xff09; String, Number, Boolean等&#xff08;都是基本数据类型的构造函数&#xff09; Object Object.keys(对象) 返回数组&…

ctf_show笔记篇(web入门---php特性)

目录 php特性 89&#xff1a;直接数组绕过preg_match当遇到数组时会直接报错输出0 90&#xff1a;这里利用了intval的特性 91&#xff1a;这里需要细节一点 92-93&#xff1a;这两题的方法很多可以发散思维 94&#xff1a;还是利用小数绕过例如4476.0 95&#xff1a;这里…

spring boot 修复 Spring Framework URL解析不当漏洞(CVE-2024-22243)

漏洞描述 当应用程序使用UriComponentsBuilder来解析外部提供的URL&#xff08;如通过查询参数&#xff09;并对解析的URL的主机执行验证检查时可能容易受到Open重定向攻击和SSRF攻击&#xff0c;导致网络钓鱼和内部网络探测等。 受影响产品或系统 6.1.0 < Spring Framew…

【bioinformation 2】生物数据库

&#x1f31e;欢迎来到AI医学的世界 &#x1f308;博客主页&#xff1a;卿云阁 &#x1f48c;欢迎关注&#x1f389;点赞&#x1f44d;收藏⭐️留言&#x1f4dd; &#x1f31f;本文由卿云阁原创&#xff01; &#x1f4c6;首发时间&#xff1a;&#x1f339;2024年3月3日&…

【新书推荐】11.1 子程序设计

第十一章 子程序及参数传递 本章先讲述子程序设计的方法&#xff0c;然后介绍在子程序调用中参数的四种传递方法。 11.1 子程序设计 在前面的示例和练习中&#xff0c;会发现程序中会有一些反复使用到的代码片段。我们将程序中反复出现的程序片段设计成子程序&#xff0c;这样…