【微知】RDMA IB verbs中的ABI是什么?作用是什么?(application binary interface、规范、兼容)

背景

在RDMA的IB verbs经常看到ABI version中的ABI是什么?

要点

ABI是什么?
ABI:application binary interface 应用二进制接口。是一种规范。一种机器级别的目标代码层接口规范。比如过程调用用的参数传递使用什么规定寄存器。不同代码段之间的通过ABI约定,比如传参和返回值在哪?内存是否对其等?。CPU、编译器和操作系统供应商都提供自己的ABI。

为什么要ABI?
为了兼容。

兼容哪些?
系统调用,函数调用,二进制格式等

举个Linux操作系统的例子

Linux的API包括一些内核接口和用户态接口。比如用户态glibc。
先看Linux ABI?
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

举个Intel芯片规范的例子:

比如SystemV在Inter386的ABI描述, http://www.sco.com/developers/devspecs/abi386-4.pdf

可以看到描述了这些规范:
比如函数调用序列,操作系统接口,ELF文件结构
在这里插入图片描述
在这里插入图片描述

比如芯片的ABI定义

寄存器的约定,比如sp就是栈指针:
在这里插入图片描述
比如栈的分布:
在这里插入图片描述

比如操作系统的ABI

比如内存中加载段的规范,数据段在哪,代码段在哪。操作系统这样规定了,编译器编译的时候就按照这个规范放到哪儿。操作系统执行的时候也就搬到哪。
在这里插入图片描述
比如微软ABI是芯片的一个自己比如对寄存器的用途约定是:

  • 调用函数传参通过寄存器RCX、RDX、R8和R9来存储前四个参数。浮点用XMM0、XMM1、XMM2和XMM3寄存器

举个应用程序的例子

以Mellanox网卡驱动中ABI的例子来看,他定义了他的二进制程序的一些规范,比如下面是create cq这个行为传参的规范,未来不同版本的用户态库,内核态响应都按照这个来兼容。

struct mlx5_ib_create_cq {
	__aligned_u64 buf_addr;
	__aligned_u64 db_addr;
	__u32	cqe_size;
	__u8    cqe_comp_en;
	__u8    cqe_comp_res_format;
	__u16	flags;
	__u16	uar_page_index;
	__u16	reserved0;
	__u32	reserved1;
};

但是!用户态verbs自己定义了ABI的版本,如果他的ABI版本提高了,就不能兼容了。不过至少ABI定义了如果你版本相同,就能兼容。

/* Increment this value if any changes that break userspace ABI
 * compatibility are made.
 */
#define MLX5_IB_UVERBS_ABI_VERSION	1

综述

因为有了ABI的规范,于是ELF这些结构也就规范了,比如也就能用相同的readelf命令读取不同平台架构(比如mac、x86、嵌入式平台)的二进制文件。包括不同程序语言之间(比如Python调用C)互相调用都离不开ABI的功能。本文主要以芯片、操作系统、用户程序为切面简单看了下ABI是什么?对理解ABI以及理解计算机体系整个结构有一定的帮助。

参考:
https://en.wikipedia.org/wiki/Application_binary_interface
https://cloud.tencent.com/developer/article/1357674

Mellanox ConnectX适配器搭配IB Verbs API是实现RDMA通信的理想组合。为了帮助你更好地理解和实践这一技术,以下是一些基本的操作步骤和编程示例。IB Verbs API提供了一套丰富的函数,用于建立和管理RDMA通信。 参考资源链接:[Mellanox InfiniBand RDMA编程用户手册](https://wenku.youkuaiyun.com/doc/649b935d4ce2147568e2e1ba?spm=1055.2569.3001.10343) 首先,你需要安装并配置好Mellanox的ConnectX系列适配器。通过适配器,你的系统可以接入InfiniBand网络,从而利用RDMA技术进行高效的数据传输。 接下来,你需要使用IB Verbs API初始化RDMA环境。这包括创建保护域(protection domain, PD)、注册内存区域(memory region, MR)以及创建队列对(queue pair, QP)。以下是创建保护域和内存区域的示例代码: ```c // 创建保护域 int pd_fd; struct ibv_pd *pd; pd_fd = ibv_open_device(pd_context); pd = ibv_alloc_pd(pd_fd); // 注册内存区域 void *local_buf = malloc(length); struct ibv_mr *mr; mr = ibv_reg先生内存(pd, local_buf, length, IBV_ACCESS_LOCAL_WRITE); ``` 在完成内存注册之后,你需要构建和初始化队列对,这涉及到建立连接和分配工作请求队列(send and receive queues)。一旦队列对就绪,你就可以通过发送和接收操作来实现远程内存的直接访问。 示例代码如下: ```c // 创建队列对 struct ibv_qp_init_attr qp_init_attr; memset(&qp_init_attr, 0, sizeof(qp_init_attr)); qp_init_attr.cap.max_send_wr = 100; qp_init_attr.cap.max_recv_wr = 100; qp_init_attr.cap.max_send_sge = 1; qp_init_attr.cap.max_recv_sge = 1; qp_init_attr.qp_type = IBV_QPT_RC; // Reliable Connection struct ibv_cq *send_cq; struct ibv_cq *recv_cq; send_cq = ibv_create_cq(pd_fd, 100, NULL, NULL, 0); recv_cq = ibv_create_cq(pd_fd, 100, NULL, NULL, 0); qp_init_attr.send_cq = send_cq; qp_init_attr.recv_cq = recv_cq; struct ibv_qp *qp; qp = ibv_create_qp(pd, &qp_init_attr); ``` 通过这些基本的步骤,你可以开始使用Mellanox ConnectX适配器和IB Verbs API进行RDMA通信。对于更深入的学习和理解,请查阅《Mellanox InfiniBand RDMA编程用户手册》,这份资料能够为你提供从基础到高级的全方位指导,帮助你在InfiniBand RDMA编程方面取得更深入的进步。 参考资源链接:[Mellanox InfiniBand RDMA编程用户手册](https://wenku.youkuaiyun.com/doc/649b935d4ce2147568e2e1ba?spm=1055.2569.3001.10343)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值