如果使用netconn API的话,udp接收过程需要用到mbox传递接收的包(传递的是指针)
mbox发送过程:
api_msg.c中recv_udp中会将接收的包发送给udp的接收mbox
sys_mbox_trypost传送的仅仅是netbuf的指针
1 static void 2 recv_udp(void *arg, struct udp_pcb *pcb, struct pbuf *p, 3 const ip_addr_t *addr, u16_t port) 4 { 5 struct netbuf *buf; 6 struct netconn *conn; 7 u16_t len; 8 9 10 buf = (struct netbuf *)memp_malloc(MEMP_NETBUF);11 if (buf == NULL) {12 pbuf_free(p);13 return;14 } else {15 buf->p = p;16 buf->ptr = p;17 ip_addr_set(&buf->addr, addr);18 buf->port = port;19 }20 21 len = p->tot_len;22 if (sys_mbox_trypost(&conn->recvmbox, buf) != ERR_OK) {23 netbuf_delete(buf);24 return;25 } else {26 /* Register event with callback */27 API_EVENT(conn, NETCONN_EVT_RCVPLUS, len);28 }29 }
在sys_mbox_trypost中,调用FreeRTOS的消息队列发送函数,这里传送的就是buf的地址了,即netbuf的指针的指针
1 err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg) 2 { 3 err_t result; 4 5 if ( xQueueSend( *mbox, &msg, 0 ) == pdPASS ) 6 { 7 result = ERR_OK; 8 } 9 else {10 // could not post, queue must be full11 result = ERR_MEM;12 }13 14 return result;15 }
mbox接收过程:
api_lib.c中完成udp的接收过程,netconn_recv主要完成TCP的接收,对于UDP其实是在netconn_recv_data函数中
1 static err_t 2 netconn_recv_data(struct netconn *conn, void **new_buf) 3 { 4 void *buf = NULL; 5 u16_t len; 6 7 *new_buf = NULL; 8 9 10 #if LWIP_SO_RCVTIMEO11 if (sys_arch_mbox_fetch(&conn->recvmbox, &buf, conn->recv_timeout) == SYS_ARCH_TIMEOUT) {12 return ERR_TIMEOUT;13 }14 #else15 sys_arch_mbox_fetch(&conn->recvmbox, &buf, 0);16 #endif /* LWIP_SO_RCVTIMEO*/17 18 19 #if (LWIP_UDP || LWIP_RAW)20 {21 LWIP_ASSERT("buf != NULL", buf != NULL);22 len = netbuf_len((struct netbuf*)buf);23 }24 #endif /* (LWIP_UDP || LWIP_RAW) */25 26 27 /* Register event with callback */28 API_EVENT(conn, NETCONN_EVT_RCVMINUS, len);29 30 LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_recv_data: received %p, len=%"U16_F"\n", buf, len));31 32 *new_buf = buf;33 /* don't set conn->last_err: it's only ERR_OK, anyway */34 return ERR_OK;35 }
在sys_arch_mbox_fetch中,msg的参数是一个指针的指针,因为要修改指针指向的位置,调用FreeRTOS的消息队列接收函数(该函数只有void*),xQrecv用的只是指针,前面post的可是指针的指针啊?
1 u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout) 2 { 3 void *dummyptr; 4 portTickType StartTime, EndTime, Elapsed; 5 6 StartTime = xTaskGetTickCount(); 7 8 if ( timeout != 0 ) 9 {10 if ( pdTRUE == xQueueReceive( *mbox, &(*msg), timeout / portTICK_RATE_MS ) )11 {12 EndTime = xTaskGetTickCount();13 Elapsed = (EndTime - StartTime) * portTICK_RATE_MS;14 15 return ( Elapsed );16 }17 else // timed out blocking for message18 {19 *msg = NULL;20 21 return SYS_ARCH_TIMEOUT;22 }23 }24 else // block forever for a message.25 {26 while( pdTRUE != xQueueReceive( *mbox, &(*msg), portMAX_DELAY ) ){} // time is arbitrary27 EndTime = xTaskGetTickCount();28 Elapsed = (EndTime - StartTime) * portTICK_RATE_MS;29 30 return ( Elapsed ); // return time blocked TODO test 31 }32 }
recv_udp netconn_recv_data(**)
netbuf *buf
try_post(*) fetch(**)
xQsend(**) xQrecv(**)
还是没太想明白~~~
知乎里有一个回答
传递指针,是需要修改指针指向的变量
传递指针的指针,是需要修改指针本身,即修改指针指向的东西。比如udp_app中定义netbuf* buf,但该指针是空的,没有指向任何东西,在netconn_recv中需要将buf指向协议栈分配的那个netbuf,就需要修改buf指向的东西,所以,需要传递buf的地址,即指针的指针,其实是指针的地址。