下载libibverbs最新代码,https://downloads.openfabrics.org/verbs/README.html 为1.2.0版本。后面开始逐步分析libibverbs源码。

1、ibv_get_device_list:

该函数具体的实现在libibverbs-1.2.0/src/devices.c文件中。

struct ibv_device **__ibv_get_device_list(int *num)
{
……
pthread_once(&device_list_once, count_devices); //count_devices这个函数在本进程中仅执行一次。具体解析见1.1
……
l = calloc(num_devices + 1, sizeof (struct ibv_device *)); //分配n个长度为size的连续空间,并将连续空间清零
…… for (i = 0; i < num_devices; ++i)
l[i] = device_list[i];
if (num)
*num = num_devices; return l;
}

1.1 pthread_once:

在多线程环境中,有些事仅需要执行一次。通常当初始化应用程序时,可以比较容易地将其放在main函数中。但当你写一个库时,就不能在main里面初始化了,你可以用静态初始化,但使用一次初始化(pthread_once)会比较容易些。
int pthread_once(pthread_once_t *once_control, void (*init_routine) (void));
功能:本函数使用初值为PTHREAD_ONCE_INIT的once_control变量保证init_routine()函数在本进程执行序列中仅执行一次。
    Linux Threads使用互斥锁和条件变量保证由pthread_once()指定的函数执行且仅执行一次,而once_control表示是否执行过。如果once_control的初值不是PTHREAD_ONCE_INIT(Linux Threads定义为0),pthread_once() 的行为就会不正常。在LinuxThreads中,实际"一次性函数"的执行状态有三种:NEVER(0)、IN_PROGRESS(1)、DONE (2),如果once初值设为1,则由于所有pthread_once()都必须等待其中一个激发"已执行一次"信号,因此所有pthread_once ()都会陷入永久的等待中;如果设为2,则表示该函数已执行过一次,从而所有pthread_once()都会立即返回0。

接着继续分析,重点函数count_devices,count_devices->ibverbs_init(init.c)。在ibverbs_init函数中,会先获取系统路径一般为/sys,然后检查内核ABI版本,对于低于或高于某个ABI版本,ibverbs就不支持了。关于ABI可以参考https://blog.csdn.net/juS3Ve/article/details/82782987,具体说ABI与cpu架构和OS有关。

接下来会检查资源限制,如下:

static void check_memlock_limit(void)
{
struct rlimit rlim; if (!geteuid())
return; if (getrlimit(RLIMIT_MEMLOCK, &rlim)) { //进程可锁定在内存中的最大数据量,字节为单位。
fprintf(stderr, PFX "Warning: getrlimit(RLIMIT_MEMLOCK) failed.");
return;
} if (rlim.rlim_cur <= 32768)
fprintf(stderr, PFX "Warning: RLIMIT_MEMLOCK is %lu bytes.\n"
" This will severely limit memory registrations.\n",
rlim.rlim_cur);
}

这里要求进程中可锁定在内存中的最大数据量,软限制要大于32K。否则会影响到内存注册。在使用时,可以在系统上设置ulimit取消限制。

接下来读取配置文件调用函数read_config(),该函数会从/sysocnfdir/libibverbs.d目录下读取配置文件,在我的系统中配置文件路径为/etc/libibverbs.d,在这个目录下内容如下:

linux-MgXfWk:/etc/libibverbs.d # ls
bnxt_re.driver cxgb4.driver hns.driver ipathverbs.driver mlx5.driver nes.driver qedr.driver vmw_pvrdma.driver
cxgb3.driver hfi1verbs.driver i40iw.driver mlx4.driver mthca.driver ocrdma.driver rxe.driver
linux-MgXfWk:/etc/libibverbs.d # cat cxgb4.driver
driver cxgb4
linux-MgXfWk:/etc/libibverbs.d # cat mlx5.driver
driver mlx5

从这些文件中读取driver名字,然后将他们加入到一个链表中,链表名称为driver_name_list。

然后是调用find_sysfs_devs函数,获取/sys/class/infiniband_verbs目录下的设备文件,查看内核代码,在uverbs_main.c中,会创建对应的设备。

那么现在的问题是:

在find_sysfs_devs函数中,会去查找sys/class/infiniband_verbs目录下的设备文件,那么这些文件是来自于哪里,是如何创建的?接下来我们来看一下,infiniband的内核代码,在内核代码中的路径为./drivers/infinniband/core/uverbs_main.c,从这个文件看起。

这个文件里有一个module_init函数,这个是模块被加载后第一个调用的模块,对应的初始化函数为ib_uverbs_init。查找编译文件,可以查看到,这个模块的名字为ib_uverbs.ko。当我们执行insmod ib_uverbs.ko时,就会调用ib_uverbs_init函数。

static int __init ib_uverbs_init(void)

我们看到这个函数,有__init标志,这个标志的意思是:

__init宏告知编译器,将变量或函数放在一个特殊的区域,这个区域定义在vmlinux.lds中。__init将函数放在".init.text"这个代码区中,__initdata将数据放在".init.data"这个数据区中。标记为初始化的函数,表明该函数供在初始化期间使用。在模块装载之后,模块装载就会将初始化函数扔掉。这样可以将该函数占用的内存释放出来。

也就是,这里的初始化函数,会在模块装载后,它使用的内存会被释放。

首先调用register_chrdev_region,该函数与alloc_chrdev_region函数一样都是向系统申请设备号,区别在于,前一个函数用于已知起始设备的设备号的情况,而alloc_chrdev_region用于设备号未知,向系统动态申请未被占用的设备号的情况。

接下来的内容,我们在下一个节展开。

RDMA——libibverbs 代码分析(1)的更多相关文章

  1. RDMA--libibverbs代码分析(2)-设备发现

    基于上一篇文章https://www.cnblogs.com/xingmuxin/p/11057845.html 我们现在从分析libibverbs代码,跳入到分析内核代码,代码位置在./driver ...

  2. Android代码分析工具lint学习

    1 lint简介 1.1 概述 lint是随Android SDK自带的一个静态代码分析工具.它用来对Android工程的源文件进行检查,找出在正确性.安全.性能.可使用性.可访问性及国际化等方面可能 ...

  3. pmd静态代码分析

    在正式进入测试之前,进行一定的静态代码分析及code review对代码质量及系统提高是有帮助的,以上为数据证明 Pmd 它是一个基于静态规则集的Java源码分析器,它可以识别出潜在的如下问题:– 可 ...

  4. [Asp.net 5] DependencyInjection项目代码分析-目录

    微软DI文章系列如下所示: [Asp.net 5] DependencyInjection项目代码分析 [Asp.net 5] DependencyInjection项目代码分析2-Autofac [ ...

  5. [Asp.net 5] DependencyInjection项目代码分析4-微软的实现(5)(IEnumerable<>补充)

    Asp.net 5的依赖注入注入系列可以参考链接: [Asp.net 5] DependencyInjection项目代码分析-目录 我们在之前讲微软的实现时,对于OpenIEnumerableSer ...

  6. 完整全面的Java资源库(包括构建、操作、代码分析、编译器、数据库、社区等等)

    构建 这里搜集了用来构建应用程序的工具. Apache Maven:Maven使用声明进行构建并进行依赖管理,偏向于使用约定而不是配置进行构建.Maven优于Apache Ant.后者采用了一种过程化 ...

  7. STM32启动代码分析 IAR 比较好

    stm32启动代码分析 (2012-06-12 09:43:31) 转载▼     最近开始使用ST的stm32w108芯片(也是一款zigbee芯片).开始看他的启动代码看的晕晕呼呼呼的. 还好在c ...

  8. 常用 Java 静态代码分析工具的分析与比较

    常用 Java 静态代码分析工具的分析与比较 简介: 本文首先介绍了静态代码分析的基 本概念及主要技术,随后分别介绍了现有 4 种主流 Java 静态代码分析工具 (Checkstyle,FindBu ...

  9. SonarQube-5.6.3 代码分析平台搭建使用

    python代码分析 官网主页: http://docs.sonarqube.org/display/PLUG/Python+Plugin Windows下安装使用: 快速使用: 1.下载jdk ht ...

随机推荐

  1. python基础语法_2基本数据类型

    http://www.runoob.com/python3   大纲 Number(数字) String(字符串) List(列表) Tuple(元组) Sets(集合) Dictionarys(字典 ...

  2. 1、网络并发编程--简介、软件开发架构、OSI七层协议

    python复习 变量与常量 基本数据类型 内置方法 字符编码.文件操作 函数 函数参数.闭包函数.装饰器 面向对象 封装.继承.多态 """ 什么是对象 数据与功能的结 ...

  3. Solution -「Code+#4」「洛谷 P4370」组合数问题 2

    \(\mathcal{Description}\)   Link.   给定 \(n,k\),求 \(0\le b\le a\le n\) 的 \(\binom{a}{b}\) 的前 \(k\) 大. ...

  4. 树莓派安装docker并使用docker图形化工具portainer

    配置环境 系统:Raspbian 11(64位) 设备:树莓派4B 一.安装docker 1.安装 curl -fsSL https://get.docker.com -o get-docker.sh ...

  5. 反射、反射机制、类加载、Class类专题复习

    一.反射概念 1.反射机制允许程序在执行期借助于ReflectionAPI取得任何类的内部信息(比如成员变量,构造器,成员方法等等),并能操作对象的属性及方法.反射在设计模式和框架底层都会用到. 2. ...

  6. vmware 16 pro 安装macos

    VMware 16 安装 MAC OS 10.13 原版(详细图文教程)关于虚拟机安装苹果系统的教程网络上有很多, 有些适合自己, 有些则不适合(教程中的版本老旧或工具资源消失), 在安装成功后选择用 ...

  7. web安全之cookie伪造

    我们注册一个用户登陆上 Cookie都是351e766803开头 我们猜把351e766803后面的值改成admin的md5值 351e766803 21232f297a57a5a743894a0e4 ...

  8. [旧][Android] ButterKnifeProcessor 工作流程分析

    备注 原发表于2016.05.21,资料已过时,仅作备份,谨慎参考 前言 在 [Android] ButterKnife 浅析 中,我们了解了 ButterKnife 的用法,比较简单. 本次文章我们 ...

  9. Smartbi扩展性怎么样,是否方便扩展开发产品已有功能?

    Smartbi大数据分析工具具有很强的扩展性,通过"稳定内核+API扩展"的架构,通过报表插件扩展的方式,能满足很多应用项目的定制化需求,把新功能无缝集成到系统中. Smartbi ...

  10. Google发布跨云Serverless管理平台Knative

    企业只要使用由Google与Pivotal.IBM.红帽和SAP等企业共同开发的跨云Serverless管理平台Knative,就能在支持Kubernetes的云平台上自由的迁移工作负载,无论是跨私有 ...