最后更新: 2026-04-07, 作者: HAO022
为什么需要 Memory Region
首先这是一块内存,且该内存主要用于RDMA 收发数据的通信场景,实际上RDMA 硬件绕过了操作系统内核直接访问这块内存。因此需要解决如下问题:
- 安全性和权限隔离:控制对本地、远程内存的读写,原子操作权限。Memory Region 提供秘钥机制,保存,验证由 HCA 硬件生成的本地、远程访问秘钥。
- 物理地址映射:将进程虚拟地址 VA 转化为 HCA 硬件可访问的IOVA、PV。 即 Memory Region MTT(Memory Translation Table)机制。
- 物理地址管理:要确保这块用于硬件读写的内存,不能被操作系统回收释放,换页,因此需要对物理页进行锁页。
- 总结:Memory Region 为后续的所有的内存操作提供条件。
如何使用
ibverbs api:
struct ibv_mr *ibv_reg_mr(struct ibv_pd *pd, void *addr, size_t length, enum ibv_access_flags access);
- pd 指定注册内存域所在的保护域
- addr length 进程虚拟地址和长度
- access 访问权限
- IBV_ACCESS_LOCAL_WRITE
- IBV_ACCESS_REMOTE_WRITE
- IBV_ACCESS_REMOTE_READ
- IBV_ACCESS_REMOTE_ATOMIC
- IBV_ACCESS_MW_BIND
- 进程的任何虚拟地址都是可以注册的,例如:
- Local memory (either variable or array)
- Global memory (either variable or array)
- Dynamically allocated memory (using malloc() or mmap())
- Shared memory
- Addresses from the text segment
- 该函数执行存在耗时,不适合在快速转发的数据平面使用
核心实现
-
ibv_reg_mr 最终调用到 HCA ib_device_ops.reg_user_mr
struct ib_device_ops mlx5_ib_dev_ops = { .reg_user_mr = mlx5_ib_reg_user_mr, }; mlx5_ib_reg_user_mr ... umem = ib_umem_get(&dev->ib_dev, start, length, access_flags); return create_real_mr(pd, umem, iova, access_flags); reg_create // 填充 MTT mlx5_ib_populate_pas(...) // 填写 MKey Context MLX5_SET(mkc, mkc, free, !populate); MLX5_SET(mkc, mkc, access_mode_1_0, access_mode); MLX5_SET(mkc, mkc, umr_en, 1); MLX5_SET64(mkc, mkc, len, umem->length); MLX5_SET(mkc, mkc, translations_octword_size, MLX5_SET(mkc, mkc, log_page_size, mr->page_shift); ... -
mlx5_ib_reg_user_mr 函数主要完成:
- ib_umem_get - pin and dma map userspace memory.
- 注册内存区域,创建填写 VA to IOVA/PA 映射表 MTT
- 创建 ib_mr,其中 lkey 为由硬件生成本地访问密钥
-
ib_umem_get
- pin_user_pages 锁页防止换页(该函数遍历页表触发缺页异常、分配物理内存)
- ib_dma_map_sgtable 物理页和 iommu 地址映射
- 映射的组织图如下:

-
reg_create
- 构建 MKey Context 并发送到 HCA。MKey Context 详细描述了 VA 信息、MTT 属性以及可以翻译成 IOVA/PA 的 MTT 表
- 返回硬件生成的 lkey, rkey

-
MLX5_IB_UPD_XLT_ENABLE
- 是否启用硬件网卡对内存地址转换表(如MTT表或间接表)的动态更新能力(动态更新而非删除再创建memory region mtt)
- Mellanox MTT/MKey 硬件配置
MTT
- IOMMU 关系:系统启用IOMMU的情况下,MTT 表存储的是IOVA,IOMMU 完成 IOVA 到 PA的转化。若未启用IOMMU,MTT表直接存储物理地址
- Mellanox HCA 硬件: 在注册内存域的场景使用的 Direct MKey

思考
-
Memory Region 锁页
- 如果不把进程VA对应物理地址锁页,那么在系统内存资源紧张时,这块物理内存很容易被回收掉。此后如果执行DMA写操作,那么极大可能会写到其他进程空间或者系统内存空间,导致系统不可用。
- Memory Region 内存是长期的并且是重复使用的,因此长期通信的过程,锁页也是一种性能的考虑。
-
内核协议栈
- 内核协议栈负责具体的数据包收发,接收流程一般使用 dev_alloc_pages,发送流程 skb_page_frag_refill alloc_pages
- MIGRATE_UNMOVABLE 内存不会被回收
-
用户态协议栈 收发数据是否需要锁页?
- 如果基于 DPDK 实现的用户态协议栈,且使用的默认大页内存,则不需要锁页,大页不支持swap。
- 如果 DPDK 配置小页申请内存,则需要考虑锁页。
篇尾:
- HUATUO 华佗是由滴滴开源并依托 CCF 孵化的操作系统深度观测项目。
- 关注微信公众号,或扫码加微信,邀请你加入用户群(请备注姓名+单位):
