本帖最后由 香水城 于 2017-8-16 11:17 编辑
LwIP 内存配置 前言
LwIP在lwipopts.h和opt.h头文件中提供了多个配置选项。用户可以根据不同的性能需求和不同应用的内存限制对协议栈用到的内存配置进行调节。Opt.h头文件中包括协议使能和设置,内存设置,调试选项等等。而Lwipopts.h头文件中集合了opt.h中一些常常需要改动的部分。一般情况下用户对lwipopts.h头文件进行修改就可以了。不管是对lwipopts.h还是opt.h进行修改,都必须保证是在已经对你所改动的内容足够的了解的情况下进行,所做的改动是正确的,否则有可能导致协议栈不能正常工作,或者效率低下。
LwIP的内存管理机制
在进行内存配置之前,我们有必要先了解LwIP的内存管理机制。
Lwip动态内存管理
LwIP中可以使用两种动态内存分配的方法:Heap和Pool的方式。
Heap的方式,每次都根据你实际需要的大小分配一块内存出来用,用完以后再还回去。
Pool的方式则是,预先将内存等分成若干份,每次分配时都拿出其中的一块或几块来。假设每等份是256bytes,而你需要300bytes的内存空间,Pool的方式就会给你分配两个256bytes的内存块(一共512bytes)。虽然有点浪费,但这种方式分配内存速度很快,非常适合在接收数据时使用。
对于Heap的方式,程序默认是使用LwIP提供的mem_malloc/mem_free进行内存的分配和释放。这种方式下,程序需要预先分配一段内存空间用来做heap分配,这段预留的空间大小通过MEM_SIZE定义。
你也可以通过C标准库里的malloc/free函数进行内存的分配和释放。需要定义宏MEM_LIBC_MALLOC。
Pbuf类型
前面说的Heap和Pool都是LwIP动态分配内存的方式。而LwIP采用了pbuf的形式管理内存中的信息,pbuf 结构既支持动态内存分配保存信息包内容,也支持让信息包数据驻留在静态存储区。pbufs 可以在一个链表中链接在一起,被称作一个 pbuf 链,这样一个信息包可以跨越几个 pbufs。
LwIP有三种类型的pbuf: PBUF_RAM, PBUF_ROM,PBUF_POOL。这三种类型拥有不同的使用目的。
1、 PBUF_RAM 类型的 pbuf 用于应用程序发送的数据被动态生成的情况。在这种情况下,pbuf 系统不仅为应用数据分配内存,还要给为这些数据预置的包头分配内存。包头大小在编译时是可配置的。MEM_SIZE定义定义了这类pbuf的可用空间大小。
2、 PBUF_ROM类型的pbuf用于应用程序要发送的数据放置在应用程序管理的存储区的情况。
3、 PBUF_POOL主要用于网络设备驱动层,因为分配一个pbuf的操作可以快速完成,所以非常适合用于中断处理。
内存配置选项
1. 接收数据缓存的大小
网络接口接收到数据包,通过以太网专用DMA放到专门的缓冲区。然后在low_level_input函数中,被拷贝到PBUF_POOL中,再将指向该PBUF_POOL的指针传递给LwIP协议栈做进一步的处理。这里用于拷贝接收到的数据的PBUF_POOL的大小由下面这两个配置选项决定:PBUF_POOL_SIZE和PBUF_POOL_BUFSIZE。
PBUF_POOL_SIZE:定义可用的PBUF_POOL的个数
PBUF_POOL_BUFSIZE:定义每个PBUF_POOL的大小
PBUF_POOL_SIZE * PBUF_POOL_BUFSIZE的值就是接收数据内存总的大小
用户需要根据接收的数据包的平均大小来设置这两个值。PBUF_POOL_BUFSIZE设置的太小,可能每个数据包都要多个pbuf来保存;设置太大,很少的数据也会占用一个较大的pbuf造成浪费。
2.发送数据缓存的大小
LwIP通过Heap的方式可分配的总内存空间大小由MEM_SIZE定义,如果应用程序需要发送大量数据,而且这些数据需要拷贝到LwIP协议栈中,那么这个值尽量设置大些。
3.连接
LwIP协议栈中通过PCB(Protocol Control Blocks)的方式管理各个连接。创建新的PCB时,也是通过memory pool的方式进行内存分配。
MEMP_NUM_UDP_PCB:定义可以创建的UDP连接个数
MEMP_NUM_TCP_PCB:定义可以创建的TCP连接个数
MEMP_NUM_TCP_PCB_LISTEN:可以创建listening TCP连接的个数
MEMP_NUM_NETCONN:使用netconn和socket编程时,该值的大小会影响可以同时创建的连接的个数
MEMP_NUM_NETBUF:使用netconn和socket编程时,该值设置太小,可能导致接收数据时分配内存失败,从而不能同时为几个连接的数据收发服务。
4. TCP选项
TCP_MSS :该值规定了TCP数据包数据部分的最大长度
TCP_SND_BUF:一个TCP连接的发送缓存空间大小。改变这个值只影响一个TCP连接可用的发送缓存空间大小。总的发送缓存空间是不会变的(由MEM_SIZE决定)。如果同时活动的TCP连接个数很多,这个值不宜设置的太大。
TCP_SND_QUEUELEN:TCP发送队列中最多的pbuf个数
TCP_WND:TCP接收窗口大小
配置正确性检查
LwIP中的很多配置并不是孤立的,在lwipopts.h和opt.h的某些配置选项前面都有说明需要满足的条件。在修改这些参数时需要特别注意。另外LwIP还提供了“sanity checks”,在编译时(LwIPv1.4.1,之前的版本是在lwip_sanity_check函数中进行检查)对lwipopts.h和opt.h中的一些关键的配置进行检查,如果发现错误就会通过error信息进行提示。该功能可以通过宏LWIP_DISABLE_MEMP_SANITY_CHECKS关闭,建议在调试时打开。
另外一个可以在配置LwIP众多选项时给你提供帮助的工具就是CubeMX。CubeMX里的LwIP配置页面对每个选项都做了详细解释,包括建议的最大/最小值。
见下图:
|