【C语言】InfiniBand驱动mlx4_init和mlx4_cleanup

一、中文注释

Linux内核模块的初始化和清理过程,针对一个称为mlx4的网络设备驱动。以下是代码的逐行中文注释:

cpp 复制代码
static int __init mlx4_init(void)
{
    int ret;

    if (mlx4_verify_params())
        return -EINVAL; // 检查设备参数是否有效,无效则返回错误码-EINVAL

    mlx4_wq = create_singlethread_workqueue("mlx4");
    if (!mlx4_wq)
        return -ENOMEM; // 创建一个单线程工作队列,若创建失败则返回错误码-ENOMEM

    ret = pci_register_driver(&mlx4_driver);
    if (ret < 0)
        destroy_workqueue(mlx4_wq); // 尝试注册PCI驱动,若失败则销毁前面创建的工作队列
    return ret < 0 ? ret : 0; // 如果注册成功,返回0;否则返回错误码
}

static void __exit mlx4_cleanup(void)
{
    pci_unregister_driver(&mlx4_driver); // 注销PCI驱动
    destroy_workqueue(mlx4_wq); // 销毁工作队列
}

module_init(mlx4_init); // 告诉内核使用mlx4_init函数来初始化这个模块
module_exit(mlx4_cleanup); // 告诉内核使用mlx4_cleanup函数来在模块卸载时进行清理

该代码是一个设备驱动模块的示例,实现了加载(初始化)和卸载(清理)时需要执行的功能。模块初始化时会创建一个工作队列,尝试注册PCI驱动;而在清理时则注销该驱动并销毁创建的工作队列。这保证了即使在初始化失败的情况下,也不会泄漏资源。

二、中文讲解

Linux内核中驱动模块的初始化和退出函数。对于内核模块来说,通常会定义初始化函数和退出函数来在模块被加载(insmod)和卸载(rmmod)时执行相应的操作。这段代码中定义了一个叫`mlx4`的网络设备驱动模块的初始化和退出逻辑。

下面逐行进行解释:

cpp 复制代码
static int __init mlx4_init(void)

这里定义了模块的初始化函数mlx4_init。__init宏表明这个函数只在初始化时被使用,之后可以被释放以节约内核空间。

cpp 复制代码
{
    int ret;

这里声明了一个整型变量ret用来存储函数返回值。

cpp 复制代码
    if (mlx4_verify_params())
        return -EINVAL;

调用一个名为mlx4_verify_params的函数,这个函数负责检查模块参数是否有效。如果不合法,函数立即返回-EINVAL(一个标准错误码,表示无效的参数)。

cpp 复制代码
    mlx4_wq = create_singlethread_workqueue("mlx4");
    if (!mlx4_wq)
        return -ENOMEM;

创建一个名为mlx4的单线程工作队列mlx4_wq,用于处理可能的异步任务。如果创建失败,返回-ENOMEM(表示内存不足)。

cpp 复制代码
    ret = pci_register_driver(&mlx4_driver);
    if (ret < 0)
        destroy_workqueue(mlx4_wq);
    return ret < 0 ? ret : 0;
}

注册PCI驱动mlx4_driver。pci_register_driver`内核提供的函数,用于注册一个PCI设备驱动。如果注册失败,则销毁之前创建的工作队列,并返回错误码。如果成功,就返回0表示初始化成功。

cpp 复制代码
static void __exit mlx4_cleanup(void)

定义模块的退出函数mlx4_cleanup。__exit宏用于声明这个函数只在模块卸载时调用。

cpp 复制代码
{
    pci_unregister_driver(&mlx4_driver);
    destroy_workqueue(mlx4_wq);
}

卸载PCI驱动mlx4_driver并销毁工作队列mlx4_wq。

cpp 复制代码
module_init(mlx4_init);
module_exit(mlx4_cleanup);

这两行宏定义告诉内核,应该在模块加载时调用mlx4_init函数,在模块卸载时调用mlx4_cleanup函数。

整个过程是:模块加载时,首先检查参数有效性;然后创建工作队列;接着注册PCI驱动。如果任何步骤失败,之前创建的资源将被清理。模块卸载时,反注册PCI驱动并销毁工作队列释放资源。

三、以太网(Ethernet)子系统与InfiniBand子系统关系

drivers/net/ethernet/mellanox/mlx4/main.c 和 drivers/infiniband/hw/mlx4/main.c两个文件中的代码都是在Linux内核中为Mellanox ConnectX 系列网络适配器编写的驱动程序的一部分,但他们服务于内核中的不同子系统。

drivers/net/ethernet/mellanox/mlx4/main.c属于以太网(Ethernet)子系统,负责处理网络相关的功能,比如以太网接口和其他标准网络协议。

  • mlx4_init_one:是一个PCI probe函数,用于初始化在PCI子系统发现的每个设备实例。当探测到Mellanox PCI设备时,这个函数会被调用。

  • __mlx4_init_one:是mlx4_init_one调用的一个辅助函数,完成设备的实际初始化。

  • mlx4_driver:定义了PCI驱动结构,包括指向各种回调函数的指针,比如设备探测(probe),关闭(shutdown),移除(remove)等。

drivers/infiniband/hw/mlx4/main.c 属于InfiniBand子系统,它处理与InfiniBand协议相关的操作。InfiniBand是一种高性能,低延迟的网络技术,主要用在高性能计算(HPC)领域。

  • mlx4_ib_init:是InfiniBand子系统的初始化函数。

  • mlx4_ib_add:在MLX4设备被Ethernet子系统初始化之后被调用,用于将IB (InfiniBand) 相关的功能添加到以太网设备上。

  • mlx4_ib_interface:定义了一个接口结构,用于在Mellanox驱动在InfiniBand和Ethernet子系统之间注册自己,和管理不同的事件和协议。

二者的关系在于Mellanox的硬件通常支持多种协议,例如以太网(Ethernet)和InfiniBand。所以,当一个Mellanox设备作为PCI设备被系统发现时,Ethernet子系统中的mlx4_driver会通过mlx4_init_one初始化以太网功能,同时它也会与InfiniBand子系统进行通信以通过mlx4_ib_add初始化InfiniBand相关功能。

在初始化过程中,Ethernet驱动可能会调用InfiniBand子系统中定义的函数。通过mlx4_interface的注册,Ethernet和InfiniBand驱动相互之间可以得知对应的设备添加(add)、移除(remove)等事件,然后执行针对InfiniBand协议所必需的操作。这允许同一硬件接口支持多个协议,而不是被锁定在单一协议上。简而言之,驱动程序通过这些接口和结构实现了模块间的通信和协同工作。

相关推荐
衍生星球3 分钟前
【网络安全】公钥密码体制
网络·安全·web安全
㣲信团队14 分钟前
ros的工作空间
linux
Dola_Pan27 分钟前
Linux系统IO-文件描述符详解
java·linux·服务器
邓豹爱学嵌入式41 分钟前
Linux应用开发实验班——JSON-RPC
linux·驱动开发·json
夜泉_ly1 小时前
C++ -引用-详解
c语言·开发语言·c++
Grayson_Zheng1 小时前
【数据结构】环形队列(循环队列)学习笔记总结
c语言·数据结构·算法
乐思智能科技有限公司2 小时前
C语言编写一个五子棋游戏-代码实例讲解与分析
c语言·开发语言·嵌入式硬件·算法·游戏
Miraitowa_cheems2 小时前
[JavaEE] HTTP/HTTPS
网络·网络协议·http