RDMA编程1 建立侦听

RDMA编程 建立连接

1. RDMA的学习环境搭建

RDMA需要专门的RDMA网卡或者InfiniBand卡才能使用,学习RDMA而又没有这些硬件设备,可以使用一个软件RDMA模拟环境,softiwarp ,
- 这是加载地址:https://github.com/zrlio/softiwarp
- 这是安装教程:http://www.reflectionsofthevoid.com/2011/03/how-to-install-soft-iwarp-on-ubuntu.html

这里也有一个RDMA编程的入门示例,
- https://github.com/tarickb/the-geek-in-the-corner
需要注意的是,这个例子里面缺省用的是IPv6连接,如果希望在IPv4环境下测试,需要先改代码用IPv4地址。

2. RDMA与socket的类比

和Socket连接类似,RDMA连接也分为可靠连接和不可靠连接。然而也不完全相同,Socket的可靠连接就是TCP连接,是流式的;不可靠连接也就是UDP,是消息式的。对于RDMA来说,无论是可靠连接和不可靠连接,都是消息式的。
编程角度看,RDMA代码也分为Server端,Client端,也有bind, listen, connect, accept,等动作,然而细节上仍有不少区别。

3. 在Server端,一个RDMA服务器的代码流程如下:

  1. rdma_create_event_channel
    这一步是创建一个event channel,event channel是RDMA设备在操作完成后,或者有连接请求等事件发生时,用来通知应用程序的通道。其内部就是一个file descriptor, 因此可以进行poll等操作。

  2. rdma_create_id
    这一步创建一个rdma_cm_id, 概念上等价与socket编程时的listen socket。

  3. rdma_bind_addr
    和socket编程一样,也要先绑定一个本地的地址和端口,以进行listen操作。

  4. rdma_listen
    开始侦听客户端的连接请求

  5. rdma_get_cm_event
    这个调用就是作用在第一步创建的event channel上面,要从event channel中获取一个事件。这是个阻塞调用,只有有事件时才会返回。在一切正常的情况下,函数返回时会得到一个 RDMA_CM_EVENT_CONNECT_REQUEST事件,也就是说,有客户端发起连接了。
    在事件的参数里面,会有一个新的rdma_cm_id传入。这点和socket是不同的,socket只有在accept后才有新的socket fd创建。

  6. ibv_alloc_pd
    创建一个protection domain。protection domain可以看作是一个内存保护单位,在内存区域和队列直接建立一个关联关系,防止未授权的访问。

  7. ibv_create_comp_channel
    和之前创建的event channel类似,这也是一个event channel,但只用来报告完成队列里面的事件。当完成队列里有新的任务完成时,就通过这个channel向应用程序报告。

  8. ibv_create_cq
    创建完成队列,创建时就指定使用第6步的channel。

  9. rdma_create_qp
    创建一个queue pair, 一个queue pair包括一个发送queue和一个接收queue. 指定使用前面创建的cq作为完成队列。该qp创建时就指定关联到第6步创建的pd上。

  10. ibv_reg_mr
    注册内存区域。RDMA使用的内存,必须事先进行注册。这个是可以理解的,DMA的内存在边界对齐,能否被swap等方面,都有要求。

  11. rdma_accept
    至此,做好了全部的准备工作,可以调用accept接受客户端的这个请求了。 –:)长出一口气 ~~ 且慢,

  12. rdma_ack_cm_event
    对于每个从event channel得到的事件,都要调用ack函数,否则会产生内存泄漏。这一步的ack是对应第5步的get。每一次get调用,都要有对应的ack调用。

  13. rdma_get_cm_event
    继续调用rdma_get_cm_event, 一切正常的话我们此时应该得到 RDMA_CM_EVENT_ESTABLISHED 事件,表示连接已经建立起来。不需要做额外的处理,直接rdma_ack_cm_event就行了

终于可以开始进行数据传输了 ==== (如何传输下篇再说)

4. 关闭连接

  1. 断开连接
    rdma_get_cm_event返回RDMA_CM_EVENT_DISCONNECTED事件时,表示客户端断开了连接,server端要进行对应的清理。此时可以调用rdma_ack_cm_event释放事件资源。然后依次调用下面的函数,释放连接资源,内存资源,队列资源。

  2. rdma_disconnect

  3. rdma_destroy_qp

  4. ibv_dereg_mr

  5. rdma_destroy_id
    释放同客户端连接的rdma_cm_id

  6. rdma_destroy_id
    释放用于侦听的rdma_cm_id

  7. rdma_destroy_event_channel
    释放 event channel

你可能感兴趣的:(RDMA)