您的位置:首页 > 科技 > IT业 > 网页游戏排行榜2017前十名_无锡品牌网站建设网站_网站百度收录批量查询_网站关键词

网页游戏排行榜2017前十名_无锡品牌网站建设网站_网站百度收录批量查询_网站关键词

2024/12/23 12:15:40 来源:https://blog.csdn.net/inputA/article/details/143461247  浏览:    关键词:网页游戏排行榜2017前十名_无锡品牌网站建设网站_网站百度收录批量查询_网站关键词
网页游戏排行榜2017前十名_无锡品牌网站建设网站_网站百度收录批量查询_网站关键词

前言

本文对lwip中TCPIP_MSG_INPKT类型消息的处理过程进行分析。

正文

在 【LwIP源码学习4】主线程tcpip_thread一文中提到。lwip主线程tcpip_thread会先从邮箱tcpip_mbox中取出消息,然后调用tcpip_thread_handle_msg函数根据消息类型对消息进行处理。

static void
tcpip_thread_handle_msg(struct tcpip_msg *msg)
{switch (msg->type) {......case TCPIP_MSG_INPKT:LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: PACKET %p\n", (void *)msg));if (msg->msg.inp.input_fn(msg->msg.inp.p, msg->msg.inp.netif) != ERR_OK) {pbuf_free(msg->msg.inp.p);}memp_free(MEMP_TCPIP_MSG_INPKT, msg);break;......}
}

在判断到消息类型msg->typeTCPIP_MSG_INPKT时,会执行这个消息对应的msg->msg.inp.input_fn函数,并传入参数msg->msg.inp.pmsg->msg.inp.netif
TCPIP_MSG_INPKT类型的消息是在tcpip_inpkt函数中被创建的。

err_t
tcpip_inpkt(struct pbuf *p, struct netif *inp, netif_input_fn input_fn)
{
......msg->type = TCPIP_MSG_INPKT;msg->msg.inp.p = p;//网卡接收到的数据msg->msg.inp.netif = inp;//网卡对应的结构体msg->msg.inp.input_fn = input_fn;//处理本包数据的函数//向tcpip_mbox邮箱中发送这个消息if (sys_mbox_trypost(&tcpip_mbox, msg) != ERR_OK) {memp_free(MEMP_TCPIP_MSG_INPKT, msg);return ERR_MEM;}
......
}

tcpip_inpkt函数在tcpip_input函数中被调用

err_t
tcpip_input(struct pbuf *p, struct netif *inp)
{
#if LWIP_ETHERNET//判断是否支持ARP协议if (inp->flags & (NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET)) {return tcpip_inpkt(p, inp, ethernet_input);} else
#endif /* LWIP_ETHERNET */return tcpip_inpkt(p, inp, ip_input);
}

如果判断相应网卡支持ARP就将ethernet_input函数设置为这包数据的处理函数。
如果不支持就把ip_input设置为处理函数,ip_input就是ip4_input函数,将这包数据作为IP数据报进行处理。
接下来是ethernet_input部分源码:

err_t
ethernet_input(struct pbuf *p, struct netif *netif)
{struct eth_hdr *ethhdr;u16_t type;
......//获取网卡接受数据的以太网首部ethhdr = (struct eth_hdr *)p->payload;
......//在以太网首部中获取本包数据的类型type = ethhdr->type;
......switch (type) {......case PP_HTONS(ETHTYPE_IP):  //如果本包数据是IP数据报......    ip4_input(p, netif);...break;case PP_HTONS(ETHTYPE_ARP): //如果本包数据是ARP数据报......etharp_input(p, netif);...break;......default:...}return ERR_OK;
}

以上代码中先从数据获取以太网首部,结构体eth_hdr内容为:

struct eth_hdr {PACK_STRUCT_FLD_S(struct eth_addr dest);PACK_STRUCT_FLD_S(struct eth_addr src);PACK_STRUCT_FIELD(u16_t type);
} PACK_STRUCT_STRUCT;

刚好对应以太网帧结构:
在这里插入图片描述
然后获取本包数据类型,并进行相应的处理。

再回到tcpip_input函数。
TCPIP_Init函数中的

netif_add(&gnetif, &ipaddr, &netmask, &gw, NULL, &ethernetif_init, &tcpip_input);

tcpip_input与网卡绑定起来,其中gnetif是网卡对应结构体,ipaddr是IP地址,netmask是子网掩码,gw是网关,ethernetif_init是网卡的初始化函数,tcpip_input是网卡消息处理函数。
netif_add函数里通过

netif->input = input;

完成绑定。之后netif->input就代表了tcpip_input函数。
ethernetif_input函数中取出网卡数据,并调用netif->input进行处理。

void ethernetif_input(void *pParams) {struct netif *netif;struct pbuf *p = NULL;netif = (struct netif*) pParams;LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n"));while(1) {//等待信号量s_xSemaphore,有说明网卡有数据需要处理if(xSemaphoreTake( s_xSemaphore, portMAX_DELAY ) == pdTRUE){......p = low_level_input(netif);//取出网卡接受到的数据...if(p != NULL){...//调用tcpip_input函数进行处理if (netif->input(p, netif) != ERR_OK){LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n"));pbuf_free(p);p = NULL;}...}}}
}

ethernetif_input函数在low_level_init函数中被创建成一个任务的执行函数。它的主要任务是等待信号量s_xSemaphore,有信号量说明网卡接受到了数据,然后取出数据做进一步处理。
s_xSemaphore信号量是在以太网接受完数据触发中断后,在回调函数里释放的。

void HAL_ETH_RxCpltCallback(ETH_HandleTypeDef *heth)
{portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;xSemaphoreGiveFromISR( s_xSemaphore, &xHigherPriorityTaskWoken );portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}

以上分析涉及到lwip处理数据的3个任务:

任务功能
网口接受数据完成中断任务用于释放网卡有数据需要处理的信号。
ethernetif_input任务用于等待网卡有消息信号,并从网卡取出数据封装成消息放入邮箱中。
tcpip_thread任务用于从邮箱中取出消息,并做进一步协议栈的处理(ARP、IP、TCP、UDP)。

在这里插入图片描述

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com