LwIP同操作系统一起工作的时候模型如下:
1.TCP/IP协议栈和应用程序以分离的任务运行
2.应用同协议栈沟通是通过API函数调用(API函数调用事实上就是通过OS自带的进程间通信机制,由应用程序与协议栈任务进行邮箱通信)
3.除上述两个任务之外,还有一个额外任务(网络接口任务),该任务由中断激活,然后任务将数据传输给协议栈
这几个任务,对应程序中函数来说的话。
TCP/IP stack task对应于tcpip_thread函数
Network Interface Task对应于ethernetif_input函数
所以在移植协议栈的过程中,需要关注ethernetif.c是针对操作系统版本还是针对裸机版本,关键是low_level_init中是否有创建线程的操作,否则协议栈不可能正常运行。
总之ethernetif.c是用来连接以太网驱动和协议栈的接口。
/********************************************************************************************************************/
同时也存在另外一种形式,即ethernetif_input不是以线程的形式运行,而是在以太网中断中被调用。
在LwIP.c中定义了一个netif的变量,在LwIP_Init中就根据ip地址,子网掩码和网关对该netif进行了初始化和添加,同时添加了两个回调函数。
struct netif *
netif_add(struct netif *netif, struct ip_addr *ipaddr, struct ip_addr *netmask,
struct ip_addr *gw,
void *state,
err_t (* init)(struct netif *netif),
err_t (* input)(struct pbuf *p, struct netif *netif))
init回调函数是该接口的初始化函数,input回调函数是将数据包传送给协议栈层(实际上是通过邮箱机制传输给协议栈层)。
netif_add(&netif,&ipaddr,&netmask,&gw,NULL,ðernetif_init,&tcpip_input);
在添加网络接口的时候,这个ethernetif_init函数就被调用用来初始化整个接口了,然后再里面继续调用会调用到ETH_Start()即允许mac进行首发数据包了。问题就剩下这个tcpip_input是什么时候调用了!
是在以太网中断函数中调用ethernetif_input函数然后该函数先调用low_level_input得到以太网帧,然后通过netif->input将该以太网帧交给协议栈。
感觉这种模式与最开始的那种模型就完全不一样了,这样中断里面就会做很多事情。(不确定这种模式在实际运行时会带来什么坏处,但理论上肯定不好,实时性受影响)
对等的,协议栈要通过以太网接口发送数据需要调用low_level_output。netif网络接口层结构体有两个一个是output,另一个是linkoutput,第一个用于arp协议,第二个才是ip协议。