1.前言
最近有一些讨论关于lwIP如何在单机的环境(比如,没有一个多线程的操作系统)使用。
本文的目的就是描述lwIP如何在无多线程操作系统或有多线程操作系统环境中运行
2.lwIP单线程内核
2.1 lwIP内核包含的组件
2.2 lwIP内核接口
2.3 单线程举例
注:上面主循环的实现可以通过ping来检测,在incontrib/ports/unix/proj/minimal/里面有一个单线程主循环的实现,你可以自己查看更多的内容。
2.4 系统定时器
2.5. 1.4.0先前的版本(TODO)
在一些lwIP的老版本中,一个简单的单线程主循环如下所示:
while() {
if(poll_driver(netif) == PACKET_READY) {
pbuf = get_packet(netif);
ip_input(pbuf, netif);
}
if (clock() - last_arp_time >= ARP_TMR_INTERVAL * CLOCKTICKS_PER_MS)
{
etharp_tmr();
last_arp_time = clock();
}
if(clock() - last_time >= TCP_TMR_INTERVAL * CLOCKTICKS_PER_MS) {
tcp_tmr();
last_time = clock();
}
}
注意:硬件定时器至少要每毫秒滴答(tick)一次,这样CLOCKTICKS_PER_MS才有效。如果你想要使用OS-tick-counter(比如,每10ms增加一次),你要调整代码如下所示:clock() - last_time >= TCP_TMR_INTERVAL / MS_PER_TICK
假如你不只使用TCP/IP和ARP,你需要增加定时器的调用次数。在一个多线程系统里,所有的定时器都在api/tcpip.c中调用,因此这个源文件是一个来检查你是否需要加入更多的定时器(比如,IP_PEASSEMBLY,DHCP,等等)的好地方。提示:在api/tcpip.c和以上例子中,定时器并不会“catch up”,意思是如果有一个定时器延迟了(不管什么原因),那么接下来的定时器滴答(ticks)也会被延迟。
3.lwIP在多线程系统中
lwIP被设计成可以在多线程系统中运行,可以和应用并发运行。
在这种情况下所有TCP/IP的处理都在一个线程中。应用线程可以通过序列API来和TCP/IP线程进行通信。
内部线程间的通信都在文件api_lib.c和api_msg.c中实现。api_lib.c包含了被应用程序使用的函数,api_msg.c实现了TCP/IP协议栈的接口。
还有一个第三文件tcpip.c来处理刚接收到的数据包和定时器事件(在先前有描述)。
当lwIP在一个多线程环境中运行,刚接收到的数据包被函数tcpip_input()(或者被tcpip_ethinput())所处理,该函数的参数与ip_input()函数相同。
这两个函数的差别在于tcpip_input()函数并不会马上处理刚接收到的数据包,它只是将数据包放在一个队列,该数据随后被TCP/IP线程处理。
当在一个多线程系统中运行,定时器事件在tcpip.c中被处理。你可以参考下面编程:
struct netif this_netif; void init()
{
memset( &my_netif, , sizeof(my_netif));
tcpip_init( ethernet_init_inside_thread, "");
} void ethernet_init_inside_thread( void *parm)
{
struct ethernetif *ethernetif;
struct ip_addr netmask; this_netif.state =NULL;
this_netif.name[] =;
this_netif.name[] =;
this_netif.output = etharp_output;
this_netif.linkoutput = low_level_output;
this_netif.next =NULL;
IP4_ADDR( &netmask, , , , );
netif_add( &this_netif, NULL, &netmask, NULL, NULL, ethernetif_init_low, tcpip_input);
netif_set_default(&this_netif);
this_netif.hwaddr_len = ETHARP_HWADDR_LEN;
this_netif.hwaddr[] = ; // or whatever u like
this_netif.hwaddr[] = ;
this_netif.hwaddr[] = ;
this_netif.hwaddr[] = ;
this_netif.hwaddr[] = ;
this_netif.hwaddr[] = ;
this_netif.mtu = ;
this_netif.flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP;
dhcp_start(&this_netif);
}