本文来自对内核源代码文档/Documentation/infiniband/user_verbs.rst的翻译和理解。
在Infiniband设备帮助下,跨计算机的两个进程可以相互访问对方的虚地址空间。在Linux操作系统上,支持进程能直接访问本地Infiniband设备的资源,从而实现跨机进程间虚地址直接通信的软件栈如下:
IB uverbs模块需要Linux内核支持CONFIG_INFINIBAND_USER_VERBS配置选项,并且核外需要安装libibverbs动态库。请参阅IB体系结构文档第11章(请问哪位大侠有该文档,请联系本人)。
libibverbs动态库给进程提供一个设备无关的API编程接口,通过/dev/infiniband/uverbsN对IB设备进行控制,主要涉及在数据传输之前的内存等资源的分配;通过用户态IB驱动提供mmap,进行高速数据传输,这里包括工作描述符和数据缓冲区的访问。
IB uverbs模块是基于Linux字符设备驱动框架下实现的,所有IB资源的创建和销毁都是通过文件描述符的命令实现,内核负责记录给到指定进程上下文的资源。IB uverbs模块维护了idr表,负责内核态地址和用户态地址之间的翻译。当进程退出时,基于进程间的资源隔离的需求,IB uverbs还需要做清除等善后工作。
libibuverbs通过用户态IB驱动直接操作工作描述符和数据缓冲区,以及相关控制寄存器。进程直接IO访问,要求物理内存一直驻留在进程的虚拟地址上,即要求物理内存钉在进程指定的虚拟地址上。IB uverbs模块通过get_user_pages()和put_page()来实现钉住物理内存和解绑的需求,并且用进程pinned_vm变量对钉住的物理内存计数,从而确保进程钉住的物理内存不会超过RLIMIT_MEMLOCK的限制。pinned_vm的数值可能大于进程实际钉住的物理内存页数量(注意:可能是因为put_page时没有将pinned_vm减小)。
另外,为了能自动创建/dev/infiniband/uverbsN设备文件,请创建一条相关的udev规则:KERNEL=="uverbs*", NAME="infiniband/%k"