RDMA技术深度剖析:本质、数据流动与核心价值
引言
在传统网络编程中,开发者在享受TCP/IP通用性的同时,也承受着它带来的性能枷锁。当CPU为了处理网络数据包而忙得不可开交时,一个根本性的问题浮现出来:为什么我们不能让数据直接从发送方的内存"飞"到接收方的内存,而不让CPU在中间当"搬运工"?
RDMA(Remote Direct Memory Access,远程直接内存访问)正是为了解决这个问题而生。本文将围绕RDMA技术的本质、数据在RDMA中的流动过程,以及它到底解决了什么问题三个维度,进行彻底而清晰的分析。
第一章:RDMA技术的本质
1.1 一个核心定义
RDMA的本质是:将网络数据传输从"CPU主导的软件流水线"转变为"硬件主导的内存直达通道"。
在传统网络中,CPU是数据传输的"总指挥"——它负责协议解析、数据拷贝、路由决策等所有环节。而RDMA的核心思想极其简洁有力:让网卡硬件直接读写用户态应用程序的内存,完全绕过操作系统内核。
1.2 实现这一本质的两大基石
基石一:内核旁路(Kernel Bypass)
应用程序通过用户态驱动(如libibverbs)直接与网卡硬件通信,无需通过系统调用进入内核。网卡的寄存器通过PCIe的MMIO(内存映射I/O)方式直接映射到用户态地址空间,应用程序可以像操作普通内存一样操作网卡。
基石二:内存注册与物理地址暴露
应用程序预先向网卡注册一段用户态内存区域(称为"内存注册",Memory Registration),网卡将这段内存的物理地址和访问密钥(L_Key/R_Key)保存在内部的MPT(Memory Protection Table,内存保护表)中。此后,网卡可以直接通过物理地址读写这片内存,无需内核映射。
这两大基石的核心价值:数据路径上彻底消灭了内核的存在。
第二章:数据在RDMA中的流动过程
理解了本质之后,我们来看数据在RDMA技术中到底是如何流动的。这里以InfiniBand架构为例,展示完整的物理路径。
2.1 预备阶段:内存注册
在数据传输开始前,应用程序必须先完成内存注册,这是整个RDMA流程的"入场券"。
操作流程:
- 应用程序调用
ibv_reg_mr(),传入用户态虚拟地址(VA)和长度 - 内核驱动将VA翻译成物理页地址(PFN)
- 物理地址、长度、权限位被写入网卡硬件的MPT(内容寻址存储器)
- 网卡返回L_Key(本地密钥)和R_Key(远程密钥)
此时的物理状态:
用户态内存页(物理地址 PA 0x10000000)
↓ 注册后
网卡MPT中新增条目:{PA: 0x10000000, L_Key: 0x1234, R_Key: 0x5678, 权限: 读写}
本质:应用程序将自己的物理内存"钥匙"交给了网卡硬件。
2.2 发送方向的数据流动
场景:应用程序A要向远程服务器B发送数据。
Step 1:数据填充(用户态完成)
应用程序直接将数据写入已注册的内存区域(VA 0x7f1234560000)
该VA对应的物理地址为 PA 0x10000000
Step 2:下发发送指令(无系统调用)
应用程序调用 ibv_post_send()
↓(用户态驱动,无系统调用)
向网卡的SQ(Send Queue,发送队列)写入WQE(Work Queue Element)
WQE(工作队列元素)的结构:
struct wqe {
uint64_t local_va; // 0x7f1234560000(本地虚拟地址)
uint32_t length; // 4096字节
uint32_t lkey; // 0x1234(本地密钥)
uint64_t remote_va; // 目标服务器已注册内存的虚拟地址
uint32_t rkey; // 目标服务器的R_Key
};
注意:SQ通过PCIe MMIO映射到用户态,写入WQE是直接写硬件寄存器,不触发系统调用。
Step 3:网卡硬件拉取数据(DMA Read)
网卡硬件轮询SQ,取到WQE
↓ 验证L_Key (0x1234)
查MPT表:L_Key 0x1234 → PA 0x10000000
↓ DMA引擎
网卡直接从物理地址 PA 0x10000000 读取4096字节数据
Step 4:硬件协议封装(完全硬件执行)
网卡硬件将原始数据封装成InfiniBand协议包,整个过程不涉及CPU:
[原始数据]
↓ 传输层硬件(BTH:Base Transport Header,含PSN序列号)
↓ 网络层硬件(GRH:Global Route Header,类似IP)
↓ 链路层硬件(LRH:Local Route Header + CRC校验)
[完整的InfiniBand数据帧]
Step 5:发送到物理链路
网卡SerDes(串行解串器)将数据转换为高速串行信号
↓ 通过光纤/铜缆
进入InfiniBand交换机网络
发送路径的数据流动总结:
用户态内存(PA) → PCIe总线 → 网卡DMA读取 → 网卡硬件封装 → 物理链路
(全程无CPU参与,无系统调用,无内存拷贝)
2.3 接收方向的数据流动
场景:远程服务器B发来一个InfiniBand数据包,目标是本机的某块已注册内存。
Step 1:物理层接收与链路层验证(硬件执行)
数据包从物理链路进入网卡
↓ 硬件解析LRH,确认是本机端口
↓ 硬件校验CRC和VCRC(变体CRC)
● 如果CRC出错:硬件自动触发链路层重传请求
● 如果通过:进入下一步
Step 2:传输层处理(硬件执行)
硬件解析GRH → 确定目标QP(Queue Pair,队列对)
↓ 解析BTH → 读取PSN(包序列号)
● 硬件检查PSN连续性
● 如果不连续:硬件自动发送NAK,等待重传
● 如果连续:进入下一步
Step 3:目标内存查找(硬件查表)
数据包中包含:远程R_Key + 远程VA
↓ 网卡硬件查MPT表
R_Key + VA → 映射到本机物理地址 PA 0x20000000
(这张MPT表在内存注册阶段已预先配置好)
Step 4:DMA写入(数据直达用户态内存)
网卡DMA引擎将数据净荷
↓ 直接写入物理地址 PA 0x20000000
这片物理地址对应的是应用程序已注册的用户态内存
Step 5:完成通知(轻量级)
网卡在CQ(Completion Queue,完成队列)中生成一个CQE
↓ 应用程序可以选择:
● 轮询模式(Polling):用户态直接读取CQ中的CQE
● 事件模式:网卡发出轻量级中断(MSI-X中断)
接收路径的数据流动总结:
物理链路 → 网卡硬件解析 → 网卡DMA写入用户态内存(PA)
(全程无CPU参与,无内核协议栈,无内存拷贝)
2.4 数据流动的完整路径对比
为了让你更清晰地看到RDMA与传统网络的本质区别,这里用一个表格来对比两种路径:
| 数据流动环节 | 传统TCP/IP | RDMA (InfiniBand) |
|---|---|---|
| 发送方数据源头 | 用户态缓冲区 | 已注册的用户态物理内存 |
| 第一次网卡访问 | 系统调用拷贝到内核sk_buff |
DMA直接读取用户态物理地址 |
| 协议封装执行者 | CPU软中断(TCP/IP栈) | 网卡硬件流水线 |
| 接收方数据终点 | 内核sk_buff→Socket队列 |
直接DMA写入用户态物理内存 |
| 数据是否发生拷贝 | 是(内核→用户态拷贝) | 否(零拷贝) |
| CPU在每个数据包上的参与度 | 高(校验、重排、窗口、ACK) | 几乎为零(仅处理完成通知) |
第三章:RDMA解决了什么问题
理解了RDMA的本质和数据流动方式后,我们来回答一个最关键的问题:RDMA到底解决了传统网络中的哪些根本性痛点?
3.1 问题一:内存拷贝导致的CPU开销
传统网络的困境:
在TCP/IP收包流程中,数据至少经历两次拷贝:
- 网卡DMA写入内核缓冲区(硬件拷贝,不消耗CPU)
skb_copy_datagram_msg将数据从内核缓冲区拷贝到用户缓冲区(CPU拷贝)
第二次拷贝是纯CPU操作,每1GB数据的拷贝大约消耗0.51个CPU核心的运算能力。在100Gb/s的网络下,仅拷贝开销就需要消耗510个CPU核心。
RDMA的解决方案:
通过内存注册,网卡直接读写用户态物理内存,完全消除了内核到用户态的拷贝。数据从网卡进入内存的那一刻,就已经在用户态地址空间中。
量化价值:
- 单机CPU利用率:传统网络在100Gb/s下需占用60%+ CPU → RDMA仅需5%以内
- 数据延迟:传统网络微秒级延迟(30-50μs) → RDMA亚微秒级延迟(1-3μs)
3.2 问题二:操作系统内核协议栈的处理延迟
传统网络的困境:
Linux内核的TCP/IP协议栈是一个软件实现的复杂状态机。每个数据包都要经历:
- 链路层MAC解析
- IP层路由查找、分片重组
- TCP层序列号检查、重排序、滑动窗口更新、ACK生成
这些全部由CPU在软中断上下文中执行。对于小包(如64字节),协议栈开销甚至超过了数据传输本身的时间。
RDMA的解决方案:
InfiniBand将整个传输层的可靠性机制(序列号、确认、重传、窗口、乱序重组)完全卸载到网卡硬件。网卡内部有专用的处理器和逻辑电路,在一个时钟周期内完成原本需要数百条CPU指令的工作。
可靠性机制的硬件实现对比:
| 传统TCP机制 | CPU执行方式 | RDMA硬件实现方式 |
|---|---|---|
| 序列号与确认 | 软中断计算ack_seq | 硬件维护PSN,自动回复ACK/NACK |
| 超时重传 | 内核定时器,软中断触发 | 硬件计时器,自动重传 |
| 滑动窗口 | CPU更新窗口值 | 链路层基于信用的流控(硬件) |
| 校验和 | CPU累加计算 | 硬件计算CRC(覆盖头部和数据) |
| 乱序重组 | sk_out_of_order_queue链表处理 |
硬件重排序缓冲区,按PSN排序交付 |
3.3 问题三:系统调用导致的上下文切换
传统网络的困境:
每一次send或recv系统调用都会触发:
- 用户态(Ring 3)→ 内核态(Ring 0)的切换
- CPU缓存(TLB、L1/L2 Cache)的部分失效
- 系统调用本身的开销(约100ns~1μs)
对于小包高频场景(如金融交易、数据库事务),系统调用开销成为主要瓶颈。
RDMA的解决方案:
通过用户态驱动(如libibverbs),应用程序可以直接操作网卡硬件寄存器(通过MMIO映射),下发WQE和读取CQE都不经过系统调用。数据路径上彻底消除了用户态/内核态的切换。
量化价值:
- 单次操作延迟:系统调用~1μs → RDMA用户态操作~0.1μs
- 每秒操作数(IOPS):传统网络~50万 → RDMA~300万+
3.4 综合对比:RDMA解决了什么
| 性能维度 | 传统TCP/IP | RDMA (InfiniBand) | RDMA带来的提升 |
|---|---|---|---|
| 端到端延迟 | 20-50μs | 1-3μs | 10-50倍 |
| CPU利用率(100Gb/s) | 60%+ | <5% | 释放50%+ CPU |
| IOPS(小包) | ~50万 | ~300万+ | 6倍+ |
| 内存拷贝次数 | 2次+ | 0次 | 消除拷贝 |
| 系统调用次数 | 每个包1-2次 | 0次(完全旁路) | 消除上下文切换 |
第四章:总结
RDMA技术的本质是将数据路径上的"CPU软件接力"替换为"硬件直达专线"。它通过两个核心机制实现这一目标:
- 内存注册:让网卡直接持有用户态内存的物理地址,使数据无需经过内核中转
- 内核旁路:通过用户态驱动和MMIO映射,让应用程序直接与网卡硬件通信
在数据流动层面,RDMA实现了从"用户态内存→网卡→网络→网卡→用户态内存"的纯硬件路径,中间没有任何CPU参与、没有任何系统调用、没有任何内存拷贝。
在解决的问题层面,RDMA彻底消除了传统网络的三重枷锁:
- 内存拷贝 → 零拷贝技术,释放CPU
- 协议栈开销 → 硬件卸载,降低延迟
- 系统调用 → 内核旁路,提升吞吐
一句话总结:RDMA让CPU从"数据搬运工"回归"计算引擎",实现了网络传输从"软件定义"到"硬件定义"的革命性转变。
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐



所有评论(0)