LwIP常见问题FAQ

11 篇文章 0 订阅
8 篇文章 0 订阅

作者:老衲五木

转自http://blog.sina.com.cn/s/blog_62a85b950102xdjx.html



1)LwIP到底稳定不稳定,能不能用在现实产品中。

首先要承认一点,世界上没有完美的软件,是软件就会有Bug,即便像Linux那样稳定和强大的系统,在极端和压力条件下,也会时不时爆出问题。LwIP源代码本生有Bug这个无可置疑(本人在其他几个文章中就罗列了好几个源代码上的问题),但我们要看到的是:LwIP版本在不断的迭代和更新,尤其是最近2.0版本出来后,就不断的更新,现在已经是最新的2.0.3了,作者们解决问题的态度和把LwIP做好的决心大家是有目共睹的。不像业界可能还存在的其他嵌入式网络协议栈,基本就处于无人维护,也无人使用的半死亡状态。

那么LwIP能不能用在现实产品中呢,我直接上一些干货,看看LwIP在哪些领域有应用,大家有兴趣的可以去详细了解。

a)基于LwIP的串口模块:有人物联串口模块,庆科串口WIFI模块,ESP8266内部用的也是LwIP

b) 使用LwIP的操作系统: 华为物联网操作系统LiteOS,
庆科MicoOS,

Freertos

c) 物联网平台:阿里云物联网云平台设备端官方代码是基于LwIP的

d) 其他:BadVPN,使用LwIP内核实现VPN连接代理;Keil,LwIP作为可选包

我们看到在各个方向都有人在用LwIP,LwIP已经可以在包括Windows,

Linux,Ucos等各种环境下运行,只要有人在用,就会暴露出它的问题,然后慢慢被解决掉。

所以我们能够肯定一点,LwIP用在产品中是完全没有问题的,有一个重点是我们要在产品发布前做好足够的测试(压力测试,异常测试),尽量解决和规避测试中遇到的问题。当然,如果大家对LwIP源代码有比较深入的了解,程序代码遵循LwIP特有的一些属性,内存资源配置合理,内核区域保护恰当,写出稳定高效的LwIP应用代码是完全可能的。

2)LwIP

2.0版本出来了后,相比以前用的最多的1.4.1版本有哪些变化。

LwIP

1.4.1版本在2012年12月正式发布,而2.0版本是在2016年11月发布,期间间隔差不多四年时间,所以在这四年之间,1.4.1无疑成为了市场上使用率最高的一个版本。也正是因为4年的沉淀,2.0版本带来了诸多的变化,这里我来给大家罗列下:

a)

常规的Bug修复,这点不必说,每个版本都会持续修改一些内核问题,2.0版本内核部分的代码变化非常之多,我们没法确认它到底更新了哪些Bug,大家有兴趣可以到官网Git仓库去看看他们的代码提交历史记录。

b)

扩充了结构体ip_addr_t的定义,用它即可以描述IPV6地址,也可以描述IPV4地址,网络层,传输层和应用层都可以通过这个结构体操作连接,而忽略IPV6和IPV4差异的细节。要说LwIP内核在2.0版本最大的变化,可能就是完善了对IPV6的支持。

c) 基本上重写了PPP拨号代码,相比以前的PPP拨号流程,2.0中的代码架构更为简洁,拨号流程更为清晰简单。

d) 添加对6lowpan类型网卡的支持,支持建立在802.15.4(Zigbee),802.15.4g(Lora,

Sigfox)等协议之上的IPV6协议,使用6lowpan,在低功耗无线自组网领域里面的每个节点都可以给自己配置一个IPv6地址,并且直接通过IPv6地址和自组网内的其他节点通信。6lowpan只支持UDP协议(相比TCP连接更简单,头部负载也更小),且6lowpan有自己的一套压缩和解压标准,会将标准IPv6数据包头部大小压缩到一个很小的范围,能够节省带宽,适合在无线自组网里面传输。在LwIP里面,可以通过添加和管理6lowpan类型网卡读取到无线网络里面的6lowpan

IPv6数据包,并将它解压成为标准的IPv6数据包,然后提交给LwIP内核处理,LwIP内核再识别UDP端口并将数据递交给对应的应用程序。从这点我们可以看到,无线自组网里面的节点也能拥有独立IP地址,且用一套标准的网络编程API实现同其他节点的通信。进一步想,如果我们在无线自组网中心节点配置NAT64这样的转换功能,可以实现IPv6地址到外部IPv4地址的转换,这样,我们的每个无线自组网节点其实就有了和公网服务器直接通信的能力,节点可以把数据直接汇报到数据中心服务器,这将是一片广阔的应用空间,无线自组网里面的节点不再是一个个孤立节点,而是真正能成为物联网末端节点的一份子。

e) 独立出一个应用程序文件夹,将各种LwIP常见应用放到了里面,主要包括有下面一些。

f) HTTP服务器,支持CGI和SSI动态网页设计,足够应用在嵌入式产品参数动态配置的场合。

g)MQTT客户端,MQTT协议是目前物联网领域最火的协议,阿里云百度云等常见物联网平台都基于这个协议部署,所以设备要接入这样的物联网平台,就必须支持mqtt协议,而这些都被LwIP集成好了。

h)SNTP协议,用这个协议可以从网络的时间服务器那里获得当前准确的世界时间。所以,如果你的设备还在用RTC,那就OUT了。

i)

TFTP协议,想直接通过控制终端(电脑)往设备上传输文件,这里就要使用TFTP协议了,可以使用在远程升级这样的应用场景。

j)MDNS/NetBIOS,这两个是和设备IP发现相关的,通过设备的名字能够在网络内解析出设备的IP地址,在物联网设备主动发现中很有用。前者基于UDP多播实现,后者通过UDP广播实现,想学UDP多播和广播的同学不妨看看这两个协议的代码是怎么做的。

k)SNMP,简单的网络设备管理协议,在旧版本中也有这部分代码,只不过这里把它单独提出来放到了应用文件夹,在局域网设备上,这个协议用的比较少。

l)

Lwipperf,一个简单的TCP服务器,可以实现服务器性能的测试,对于每个连上服务器的客户端,服务器会下压大量数据,以此统计带宽。另外,我们常见的服务器性能测试方式还有回显,客户端连上服务器后,不断向服务器发送数据,服务器收到数据后将数据原样返回,客户端通过统计发送和接收的数据量来统计到服务器的双向带宽。

注意,这里的所有这些应用都是基于LwIP的raw编程实现的,他们运行时是驻留在和内核同样线程中,所以想学raw编程的同学可以好好看看这些例程。

 

3)TCP服务器如何支持多并发连接,为什么我的服务器连接连不上,服务器不稳定?

嵌入式设备的典型特点是内存限制,我们在Windows或者Linux这样的大系统下进程应用程序设计的时候,基本不用担心申请不到内存的情况出现。但是在嵌入式领域就不一样了,大不数的小设备只有几十K或者几百K的内存空间,当LwIP运行于这些设备中的时候,就经常会出现内存不够的问题,可以说,你碰到的LwIP使用问题中,90%以上是因为内存失败而引发的。LwIP中需要动态申请内存的地方非常多,而网络协议栈的本质也就是对内存,对数据包不断处理和上层传递的过程。

我们这里来讨论下,要TCP服务器支持多客户端并发连接,你最需要配置的几个参数。首先必须明白一点,内核中一条TCP连接由一个TCP控制块来描述,TCP控制块的个数决定了内核能够支持的最大连接数。所以,

3.1)如果你是用RAW接口实现服务器,那么内核宏MEMP_NUM_TCP_PCB决定了你能支持的最大连接数:

       

#define

MEMP_NUM_TCP_PCB   

5  //最大支持5条连接,注意服务器自己会占用掉一条连接

3.2)如果你使用的是Netconn或者socket接口实现服务器,那么除了配置上面这个宏以外,还需要配置:

        #define

MEMP_NUM_NETCONN

5
//这个宏是应用层用来描述一个TCP连接的数据结构,它内部会最终引用到内核的TCP控制块。所以这个结构体个数应该设置的和MEMP_NUM_TCP_PCB相同

       

此外,基于Netconn或者socket实现服务器时,它和我们的操作系统资源就密不可分了,我们必须要移植操作系统模拟层才能够使用这两种API。模拟层移植中,就包括了对操作系统邮箱(队列)和信号量资源的占用。所以,你要统计好每个连接对操作系统资源的基本消耗是多少。我提取了连接里面的一些和操作系统相关的重要信息:

                  

struct netconn {

                       

sys_sem_t op_completed;

                       

sys_mbox_t recvmbox;

                       

sys_mbox_t acceptmbox;

                       

......

                  

}

   

可以看出,每条连接至少要消耗一个信号量和两个邮箱,在大部分的LwIP移植方式中,邮箱可以基于锁+信号量的方式来实现(参见《嵌入式网络那些事—STM32物联实战》),既一个邮箱要消耗两个信号量。这样算下来,一条TCP连接就要消耗5个操作系统信号量,因此,如果操作系统信号量资源配置的不够,新连接就建立不起来,在UCOSII操作系统中,我们应该这样配置信号量资源:

                     

#define

OS_MAX_EVENTS MEMP_NUM_NETCONN*5+EVENTS_MAX

如果你使用的是其他移植方式,请参考我们前面的分析方法,正确的配置系统各个资源。

 

到这里,有同学就会说了,LwIP怎么这么复杂,这么多配置需要自己根据实际情况去设置。确实这样,在你没有彻底理清楚内核的工作原理和内存在哪里会使用,是很难做好这些配置的(这样是为什么要鼓励大家来参加我的LwIP和网络培训的目的^^)。只有真正摸清它的原理,知道它内部的细节,自己才能灵活自如的配置,写出稳定高效的网络应用程序出来。

最后,有没有方法减少这些内存错误呢,毕竟要每个人都花时间去理清楚内核的细节,也是不容易的。这里有个简单的方法,可以减少大部分的内存错误,在配置文件中配置如下宏:

                         

#define

MEMP_MEM_MALLOC            1

                         

#define

MEM_SIZE                              

MAX   //定义成可以使用的最大值

上面这两条,第一条意思是,禁止使用LwIP自己的内存池分配方式(内存池分配速度比较快,但是硬伤是你得对每个池子的个数进行正确配置,这点对初学者很难),当内核请求内存池分配内存的时候,我们使用内存堆分配方式代替;第二条,表示加大你的内存堆大小,你能加多大就多大,通常我们可以设置为系统的总内存大小减去你的所有ZI+RW数据区的大小,即你的物理内存除了全局变量占用的空间外,剩下的都给LwIP用。这样我们能保证LwIP管理的内存堆足够大,能最大程度的保证各种动态分配能够成功。

  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值