《LwIP协议栈源码详解——TCP/IP协议的实现》API消息机制 lwip协议栈详解

《LwIP协议栈源码详解——TCP/IP协议的实现》API消息机制 lwip协议栈详解

现在有必要来看看前面一直提到的内核协议栈进程是什么样子的。这个函数叫tcpip_thread,其源码如下,其中去掉了不相关的编译选项和非重点讨论部分。

static void tcpip_thread(void *arg)

{

structtcpip_msg *msg;

sys_timeout(IP_TMR_INTERVAL,ip_reass_timer, NULL);//创建IP分片重装超时事件

sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL);//创建ARP超时事件

while (1){// 进程循环

sys_mbox_fetch(mbox,(void*)&msg);// 阻塞在邮箱上接收要处理的消息

switch(msg->type) { // 判断消息类型

caseTCPIP_MSG_API: // 若是API消息,调用消息内部的function函数

msg->msg.apimsg->function(&(msg->msg.apimsg->msg));

break;

caseTCPIP_MSG_INPKT:// 若是接收到IP层递交的数据包

if(msg->msg.inp.netif->flags & NETIF_FLAG_ETHARP) //支持ARP

ethernet_input(msg->msg.inp.p,msg->msg.inp.netif);//先进行ARP处

//理,再判断是否递交IP层处理

else //否则直接递交给IP层

ip_input(msg->msg.inp.p, msg->msg.inp.netif);

memp_free(MEMP_TCPIP_MSG_INPKT,msg);

break;

。。。。。。

default:break;

}//switch

} //while

}//

邮箱mbox是协议栈初始化时建立的用于tcpip_thread接收消息的邮箱,该函数能够识别的消息类型是tcpip_msg结构的,所以不管是API部分还是IP数据包输入部分,都必须将自己的信息封装成tcpip_msg结构。

struct tcpip_msg {

enum tcpip_msg_type type;// 枚举结构,消息类型

sys_sem_t*sem; //信号量指针,该字段似乎没怎么被用到

union {// 共用体,不同消息类型使用不同的结构

structapi_msg *apimsg; // API消息指针

structnetifapi_msg *netifapimsg; // 不讨论

struct{// 接收到IP层数据包相关指针

struct pbuf *p;

struct netif *netif;

} inp;

struct{ // 不讨论

void (*f)(void *ctx);

void *ctx;

} cb;

struct{ // 不讨论

u32_t msecs;

sys_timeout_handler h;

void *arg;

}tmo;

} msg; //枚举类型的名字

};

这个结构和上节讨论的api_msg_msg有着很相似,api_msg_msg里面也包含了一个叫做的msg的结构体。枚举型tcpip_msg_type的内部成员就是在函数tcpip_thread中看到的TCPIP_MSG_API和TCPIP_MSG_INPKT等,这里只讨论这两种类型。

API函数内部调用来向内核进程发送消息的函数叫tcpip_apimsg,该函数填充一个TCPIP_MSG_API类型的tcpip_msg结构,并把该结构投递到协议栈阻塞的邮箱mbox:

err_t tcpip_apimsg(struct api_msg *apimsg)

{

struct tcpip_msgmsg;// 定义一个消息变量

if (mbox != SYS_MBOX_NULL) {

msg.type= TCPIP_MSG_API; // 消息类型

msg.msg.apimsg = apimsg; //使用tcpip_msg中的msg.apimsg字段记录相关信息

sys_mbox_post(mbox, &msg); // 投递消息

sys_arch_sem_wait(apimsg->msg.conn->op_completed, 0);//阻塞,等待内核处理完毕

returnERR_OK;

}

return ERR_VAL;

}

底层向内核进程递交接收到的IP数据包是通过调用网络接口结构netif中指针input指向的函数来实现的(参见前面netif描述的部分)。通常这个函数是tcpip_input。

err_t tcpip_input(struct pbuf *p, struct netif *inp)

{

struct tcpip_msg *msg; // 定义了一个消息指针

if (mbox != SYS_MBOX_NULL) {

msg =memp_malloc(MEMP_TCPIP_MSG_INPKT); //为新的消息申请空间

if (msg== NULL) {

return ERR_MEM;

}

msg->type = TCPIP_MSG_INPKT; // 消息类型

msg->msg.inp.p = p; //使用tcpip_msg中的msg.inp字段记录相关信息

msg->msg.inp.netif = inp;

if(sys_mbox_trypost(mbox, msg) != ERR_OK) { // 投递一次消息

memp_free(MEMP_TCPIP_MSG_INPKT, msg);//投递不成功则删除消息

return ERR_MEM;

}

returnERR_OK;

}

return ERR_VAL;

}

哎,这个过程是十分的复杂纠结啊,下面这个图可能更容易理解。这里函数tcpip_thread还是只处理TCPIP_MSG_API和TCPIP_MSG_INPKT这两种类型的消息。


从上面的图中可以清晰的看出两部分API函数之间的交互过程,以及应用程序和内核函数之间的交互过程。API函数netconn_xxx在文件api_lib.c中,而API实现的另一部分函数do_xxx在api_msg.c中。

接下来的一节我们将精力集中在api_lib.c中的各个函数,而不去过多关心api_msg.c中的各个do_xxx是怎样与内核函数交互完成相关工作的。netconn_xxx函数在LwIP说明文档16小节也有相关的描述,这里打算再重复的描述下各个函数的功能以及它们的实现过程。

  

爱华网本文地址 » http://www.aihuau.com/a/25101016/322174.html

更多阅读

2006-2010年高考语文四川卷分类详解 四川麻将 源码详解

【转载】2006-2010年高考语文四川卷分类详解一、字音1.下列词语中,加点字的读音全部正确的一组是(06)A.模样(mó) 疲惫(bèi) 濒临绝境(bīn) 并行不悖(bèi)B.麻痹(bì) 包庇(bì) 心潮澎湃(bài) 步履蹒跚(pán)C.贮藏(zhù) 鞭笞(chī) 瞠目结舌(c

《解说一下,烧冥钱、金元宝等的理由》 冥钱纸包封面怎么写

有句玩笑话,叫上坟烧报纸,糊弄鬼呢,这句话有两层意思,一是现在的报纸,夹杂了太多虚假内容,无论是广告,还是小道消息,都是乱七八糟,就如今天的网络仙道大论谈,真假混杂,让人无所适从。另一层意思,用报纸上坟,是欺骗鬼的行为,报纸和冥钱都是纸张,为什

声明:《《LwIP协议栈源码详解——TCP/IP协议的实现》API消息机制 lwip协议栈详解》为网友不需要眼泪分享!如侵犯到您的合法权益请联系我们删除