对RDMA理解(2)
总览
struct ibv_qp_init_attr → 创建 QP 通道时用的“配置单” 告诉网卡:我要建一个什么样的收发通道。
struct ibv_send_wr → 发送数据的“任务单” 告诉网卡:我要发什么数据、发到哪里、怎么发。
struct ibv_recv_wr → 接收数据的“任务单” 告诉网卡:我准备好一块内存,你来把数据放进来。
1. struct ibv_qp_init_attr —— QP 初始化属性
作用
创建 QP(队列对)之前,填写的“配置表” 你要告诉系统:我想要一个什么类型、多大、绑定哪个 CQ 的 QP。
小白能懂的比喻
你要开一个快递站(QP),这个结构体就是:
快递站多大(能存多少包裹)
用哪个通知器(CQ)
是发快递用、收快递用,还是都用
核心字段(只记最重要的)
struct ibv_qp_init_attr {
// 1. 发送队列最大能放多少个发送请求
int cap.max_send_wr;
// 2. 接收队列最大能放多少个接收请求
int cap.max_recv_wr;
// 3. 发送完成后,用哪个 CQ 通知你
struct ibv_cq *send_cq;
// 4. 接收完成后,用哪个 CQ 通知你
struct ibv_cq *recv_cq;
// 5. QP 类型(99% 用 IBV_QPT_RC 可靠连接)
enum ibv_qp_type qp_type;
};
小白必须记住
这是创建 QP 前必须填的表
不填这个表,系统不知道给你建多大的通道
最常用类型:IBV_QPT_RC(可靠连接,不会丢包)
2. struct ibv_send_wr —— 发送工作请求(发数据任务单)
作用
你给网卡下达的“发送命令” 网卡看到这个结构体,就会自动去内存拿数据,发给对方。
比喻
这是一张快递发货单:
货物在哪(内存地址)
发多大
用哪个通道发
发完怎么通知
核心字段(小白必懂)
struct ibv_send_wr {
// 1. 用哪个 QP 通道发(必须填)
struct ibv_qp *qp;
// 2. 要发送的数据放在哪里(必须填)
struct ibv_sge *sg_list;
// 3. 发送方式(最常用:IBV_WR_SEND 普通发送)
enum ibv_wr_opcode opcode;
// 4. 发完后,任务完成时带回的标识(你自己定义)
uint64_t wr_id;
};
关键子结构体 struct ibv_sge(发送数据的位置)
struct ibv_sge {
uint64_t addr; // 数据起始地址
uint32_t length; // 数据长度
uint32_t lkey; // 内存 MR 的钥匙(必须!)
};
小白必记
ibv_send_wr = 发数据指令
必须绑定 sge = 数据在哪
必须给 lkey = 网卡访问内存的密码
3. struct ibv_recv_wr —— 接收工作请求(收数据任务单)
作用
提前告诉网卡:我准备好内存了,你来把数据放进来 RDMA 接收必须提前提交接收请求,不然数据来了没地方放。
比喻
这是一张快递收货预约单:
我准备好空箱子了
箱子多大
放我家哪个位置
核心字段
struct ibv_recv_wr {
// 1. 用哪个 QP 通道接收
struct ibv_qp *qp;
// 2. 数据接收后放在哪里(必须填)
struct ibv_sge *sg_list;
// 3. 接收完成时,带回的标识
uint64_t wr_id;
};
小白必记
接收必须提前提交
网卡不会帮你分配内存,你必须自己准备好
用 ibv_recv_wr 告诉网卡内存位置
三者关系
你先填:ibv_qp_init_attr
↓
创建出:QP 通道(真正收发数据的管道)
↓
发数据:用 ibv_send_wr 下达发送任务
↓
收数据:用 ibv_recv_wr 提前提交接收任务
小白终极总结(3 句背会)
ibv_qp_init_attr → 建通道前的配置表
ibv_send_wr → 让网卡发数据的任务单
ibv_recv_wr → 让网卡收数据的任务单
参考链接 :0voice · GitHub
