@@ -115,6 +115,15 @@ rdma_listen(listener, 10);
115115* 创建QP:
116116
117117```
118+ qp_attr->send_cq = s_ctx->cq;
119+ qp_attr->recv_cq = s_ctx->cq;
120+ qp_attr->qp_type = IBV_QPT_RC;
121+
122+ qp_attr->cap.max_send_wr = 10;
123+ qp_attr->cap.max_recv_wr = 10;
124+ qp_attr->cap.max_send_sge = 1;
125+ qp_attr->cap.max_recv_sge = 1;
126+
118127rdma_create_qp(id, s_ctx->pd, &qp_attr);这里要注意的是qp_attr,顾名思义,qp的属性,那么qp的类型也就是在这个结构中指定,以RC连接类型为例:qp_attr->qp_type = IBV_QPT_RC;
119128```
120129
@@ -161,9 +170,11 @@ ibv_reg_mr( s_ctx->pd, conn->send_region, BUFFER_SIZE,IBV_ACCESS_LOCAL_WRITE | I
161170
162171```
163172wr.sg_list = &sge;
173+
164174sge.addr = (uintptr_t)conn->recv_region;
165175sge.length = BUFFER_SIZE;
166176sge.lkey = conn->recv_mr->lkey;
177+
167178ibv_post_recv(conn->qp, &wr, &bad_wr);
168179```
169180
@@ -174,6 +185,12 @@ ibv_post_recv(conn->qp, &wr, &bad_wr);
174185```
175186wr.opcode = IBV_WR_SEND;
176187wr.send_flags = IBV_SEND_SIGNALED | IBV_SEND_INLINE;
188+ wr.sg_list = &sge;
189+
190+ sge.addr = (uintptr_t)conn->send_region;
191+ sge.length = BUFFER_SIZE;
192+ sge.lkey = conn->send_mr->lkey;
193+
177194ibv_post_send(conn->qp, &wr, &bad_wr);
178195```
179196
@@ -182,10 +199,22 @@ ibv_post_send(conn->qp, &wr, &bad_wr);
182199event-triggered polling指的就是需要下面前三行事件通知的代码,busy polling就不需要前三行代码,直接循环地poll cq,因此消耗更多的CPU。
183200
184201```
185- ibv_get_cq_event(s_ctx->comp_channel, &cq, &ctx);
186- ibv_ack_cq_events(cq, 1);
187- ibv_req_notify_cq(cq, 0);
188- ibv_poll_cq(cq, 1, &wc);
202+ void * poll_cq(void *ctx)
203+ {
204+ struct ibv_cq *cq;
205+ struct ibv_wc wc;
206+
207+ while (1) {
208+ TEST_NZ(ibv_get_cq_event(s_ctx->comp_channel, &cq, &ctx));
209+ ibv_ack_cq_events(cq, 1);
210+ TEST_NZ(ibv_req_notify_cq(cq, 0));
211+
212+ while (ibv_poll_cq(cq, 1, &wc))
213+ on_completion(&wc);
214+ }
215+
216+ return NULL;
217+ }
189218```
190219
191220### 2.4 write/read
0 commit comments