lwip【5】 lwIP配置文件opt.h和lwipopts.h初步分析之二
如何去配置lwip,使它去适合不同大小的脚,这就是本贴的主题lwIP的配置问题。尤其是内存的配置,配置多了浪费,配置少了跑不了或者不稳定(会出现的一大堆莫名奇妙的问题,什么打开网页的速度很慢啊?什么丢包啊,什么死机啦,什么跑到无限循环里边去了,总之很多)。
在这里先说一下这两个配置lwip协议栈文件opt.h和lwipopts.h的关系:
opt.h是lwip“出厂”时原装的配置文件,它的作者是瑞士科学院的Adam等人,而lwipopts.h的作者是stellarisWare的工程师,它集合了opt.h中常常需要改动的部分和针对Stellaris所特有的配置选项添加进来了。这两个文件里边都配置的选项,以后者为准,不是共有的选项以它们各自的配置为准。
在这里先说一下lwip的内存管理机制,我们以enet_lwip这个例程为例。
在使用lwip的时候,我们可以使用两种形式的内存,一种是heap(mem.c文件-mem_malloc()),一种是pool(memp.c文件-memp_malloc())。heap就像是一整块蛋糕,我们需要多少就切多少,但是切了之后不能吃,只能看,因为看完之后,你还要放回去让别人看,因为当整块蛋糕很少的时候,有很多人等着都要切了看,这样很多次的切了之后又放回去,必然要产生一些很小的蛋糕块,这就是内存的碎片,到最后都是切得很细的蛋糕块,假如这个时候你想切块大点的蛋糕来看看,不好意思,你找遍了整个拼凑起来的蛋糕块,没有发现你想要的那么大的,结果你只好放弃了,所以最后内存申请回频频失败。
因为我们是嵌入式系统,我们的RAM再大也不能和PC机的天文数字相比,我们不能使用PC机所使用的蛋糕刀具来切蛋糕,必须使用更小型的道具,占用CODE更小,这一点Adam等相对于标准C而实现了几个小的内存分配、重分配和释放函数,它们都以mem_为前缀,已和原来的标准库函数相区别。当然如果你偏要使用大的刀,只需要
#define MEM_LIBC_MALLOC 1 。
这几个工具不管你是heap型模式切蛋糕还是pool模式切蛋糕,都可以用它们来完成,它们只是刀,至于怎么切蛋糕,这里不是它们该考虑的事情。
上面介绍了heap型的切蛋糕的方法,在简单说一下pool型切蛋糕的方法。
为了能让更多的人把蛋糕切回去看并且不至于还回来的蛋糕都是非常地小。Adam非常努力地在lwip切蛋糕上问题上采用一种Pool型的切法,找来一块蛋糕,把它切成n等分,每一份都是相同的固定大小,一份不够的可以拿两份,一份用起来太多的人你也最少拿一份(虽然浪费了,但是你也必须这么做),这种切法有两个好处,一是:现在你不能再随便的按自己的要求大小去切蛋糕了,大小是固定的,这样你申请了蛋糕之后不需要去切了,已经切好了,你可以很快地拿到一份大小固定的蛋糕,这非常适合于在接受数据帧的底层使用,当大量的数据来的时候,我们一下子需要很多的内存,这种方式下,我们很快就可以拿到足量的内存,不至于应接不暇;二是:在切成多少份,每份多大上需要我们根据最常接受到的数据帧的大小来费点脑筋,切得太小了,内存的利用率就下降了,切得太大了,我们就会严重地浪费内存,如果总共可切的内存还不大的话,那肯定是要因为后面来的数据无蛋糕可切而要丢包的,这就像是现在的房地产,少数富人拥有好几套大房子空着不住人,而另一方面,多数穷人却因为租不起房子而只好离开大城市,但是当前穷人对于城市所作的贡献并不见得比富人小。
这两种切法都不是完美的,也不可能有完美的,但是有它们最适合的地方。我上面的比喻是为了更形象地理解,当然在细节上可能会有不同,不过,大体上就是这么个意思,细节我们可以去深入地分析。
Pool型一般用于从链路层就收一个帧,目的是快速、少碎片、浪费一点没关系、只要我能满足大多数人迅速地有房可住即可。
heap型一般用于缓存应用层生成的数据,大小自己定,相切多少切多少,随心所欲,尽管以后可能没得切,但我只在乎现在,也许以后就有新的方法解决呢,就像煤炭和石油,该用还得用,说不定以后会有新能源取代它们,杞人忧天干嘛。
实际上,在enet_lwip这个例程里它就是这么实现的。
如何配置heap的大小呢,
#define MEM_SIZE (12 * 1024) ----实际空间即固定数组ram_heap[]中 (用于PBUF_RAM类型 p->len = p->tot_len)
主要mem.c文件---mem_malloc()
#define MEM_SIZE_ALIGNED     LWIP_MEM_ALIGN_SIZE(MEM_SIZE)
static u8_t ram_heap[MEM_SIZE_ALIGNED + (2*SIZEOF_STRUCT_MEM) + MEM_ALIGNMENT];
所以说当你有大量的数据要发送的时候,你最好把这个值设置得大一些。否则你会因为切不到heap中的内存而无法发送或只能延迟发送。
最好是把上面这个数设置成4字节对齐的。
如何配置pool的大小呢,
#define PBUF_POOL_SIZE 16
#define PBUF_POOL_BUFSIZE 256 ---实际空间即固定数组memp_memory[]中(PBUF_POOL类型 p->tot_len= p->len + p->len.....)
主要memp.c文件---memp_malloc()
LWIP_PBUF_MEMPOOL(PBUF_POOL, PBUF_POOL_SIZE,           PBUF_POOL_BUFSIZE,             "PBUF_POOL")
static u8_t memp_memory[MEM_ALIGNMENT - 1 
#define LWIP_MEMPOOL(name,num,size,desc) + ( (num) * (MEMP_SIZE + MEMP_ALIGN_SIZE(size) ) )
#include "lwip/memp_std.h"
];
case PBUF_POOL:
p = memp_malloc(MEMP_PBUF_POOL);
case PBUF_RAM:
p = (struct pbuf*)mem_malloc(LWIP_MEM_ALIGN_SIZE(SIZEOF_STRUCT_PBUF + offset) + LWIP_MEM_ALIGN_SIZE(length));
 case PBUF_ROM:
 case PBUF_REF:
 /* only allocate memory for the pbuf structure */
 p = memp_malloc(MEMP_PBUF);
第一个是我们要切的分数,第二个是每一份的大小。
那么实际上我们切到的每一份内存的大小要比我们定义的大16个字节。我们可以根据应用去调整这几个值,这两部分的大小就占到了lwip协议栈所占内存的大部分,也就是说他们会影响到ZI段的大小。
如果要使发送的应用程序也采用pool的方式而不是heap,则要: 
#define MEM_USE_POOLS 1 
define MEM_USE_CUSTOM_POOLS 1 
并且还要在工程所在目录下创建文件 
lwippools.h,里包括: 
LWIP_MALLOC_MEMPOOL_START 
LWIP_MALLOC_MEMPOOL(20, 256) 
LWIP_MALLOC_MEMPOOL(10, 512) 
LWIP_MALLOC_MEMPOOL(5, 1512) 
LWIP_MALLOC_MEMPOOL_END 
这样协议栈所涉及到的内存都用POOL方式来管理了,这种方法在StellarisWare例程中一般没有采用。 
如果使用POOL,以下关于内存的两个函数是不会被调用的: 
mem_init();这个函数主要是对堆内存的初始化,并返回指针。 
mem_realloc(mem, size);这个函数对已分配的对内存块进行收缩。
lwip【5】 lwIP配置文件opt.h和lwipopts.h初步分析之二的更多相关文章
- lwIP配置文件opt.h和lwipopts.h
		如何去配置lwip,使它去适合不同大小的脚,这就是lwIP的配置问题.尤其是内存的配置,配置多了浪费,配置少了跑不了或者不稳定(会出现的一大堆莫名奇妙的问题,什么打开网页的速度很慢啊?什么丢包啊,什么 ... 
- lwip【4】 lwIP配置文件opt.h和lwipopts.h初步分析之一
		在这里先说一下这两个配置lwip协议栈文件opt.h和lwipopts.h的关系: opt.h是lwip"出厂"时原装的配置文件,它的作者是瑞士科学院的Adam等 ... 
- sys/types.h fcntl.h unistd.h sys/stat.h
		sys/types.h 是Unix/Linux系统的基本系统数据类型的头文件,含有size_t,time_t,pid_t等类型. 在应用程序源文件中包含 <sys/types.h> 以访问 ... 
- 单片机中用c编程时头文件reg51.h及reg52.h解析
		单片机中用c编程时头文件reg51.h及reg52.h解析 我们在用c语言编程是往往第一行就是reg51.h或者其他的自定义头文件,我们怎么样来理解呢? 1)“文件包含”处理. 程序的第一行是一个“文 ... 
- windows.h和winsock2.h包含顺序问题(转)
		windows.h和winsock2.h有类型重定义我是知道的,本来就一个库来说没问题,把winsock2放到windows.h前或先定义WIN32_LEAN_AND_MEAN都能解决问题但现的出了问 ... 
- VS2013使用winsock.h和winsock2.h发生冲突后的终极解决方法
		问题:彻底无语了,不小心某个文件包含了windows.h头文件,而windows.h文件里面包含着winsock.h文件, 如果你下次使用winsock2.h文件时,位置不对,然后编译器会给你一大堆重 ... 
- [转]rpcndr.h和wtypes.h冲突Bug的解决方案
		[转]rpcndr.h和wtypes.h冲突Bug的解决方案 http://blog.csdn.net/tzwh_86/article/details/9495133 rpcndr.h和wtypes. ... 
- 已经包含了#include <atlcom.h>  #include <comutil.h>还是报错
		在WTL工程的.h中 #include <atlbase.h>#include <atlcom.h>#include <atlcomcli.h>#include & ... 
- c语言string.h和memory.h某些函数重复问题
		在C语言中,为了使用memset()函数,你是选择#include <string.h>还是<memory.h>?两个都可以,如何选择? <string.h>,标准 ... 
随机推荐
- PHP服务端如何通过程序将图上传到指定的图片服务器与图片服务器的优化方案
			一:PHP服务端如何通过程序将图上传到指定的图片服务器与图片服务器的优化方案 (1) php服务器把图片处理成缩率图或指定大小的图片在通过PHP程序代码 操作FTP 上传到图片服务器. 二:图片服务器 ... 
- linux   经常使用命令
			帮助信息 ./configure -help|grep mysql 安装php ./configure --prefix=/usr/local/fastphp --with-mysql=mysqlnd ... 
- 多媒体开发之---h264中 的RTP PAYLOAD 格式
			H.264 视频 RTP 负载格式 1. 网络抽象层单元类型 (NALU) NALU 头由一个字节组成, 它的语法如下: +---------------+ |0|1|2|3|4|5|6|7 ... 
- HDU 5338(ZZX and Permutations-用线段树贪心)
			ZZX and Permutations Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/O ... 
- OIer同样是音乐家
			烦闷的时候,shenben为大家准备了2首歌(不用耳机也能听哦) 只需把代码复制到dev-c++的编辑器上,轻按F11,然后聆听OIer的音乐…… 千本樱 曲谱 #include <cstdio ... 
- EasyPlayerPro(Windows)流媒体播放器开发之框架讲解
			EasyPlayerPro for Windows是基于ffmpeg进行开发的全功能播放器,开发过程中参考了很多开源的播放器,诸如vlc和ffplay等,其中最强大的莫过于vlc,但是鉴于vlc框架过 ... 
- 九度OJ 1154:Jungle Roads(丛林路径) (最小生成树)
			时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:832 解决:555 题目描述: The Head Elder of the tropical island of Lagrishan has ... 
- runsv
			runsv(8) manual page http://smarden.org/runit/runsv.8.html Name runsv - starts and monitors a servic ... 
- 宿舍更换的新淋浴喷头"水温vs旋钮角度"关系的研究(曲线)
			版权声明:我极少创造新知识,大部分情况下是个知识的二道贩子 https://blog.csdn.net/stereohomology/article/details/24478825 应该非常一目了然 ... 
- 2.2链表 链表中倒数第k个结点
			aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAApQAAAENCAIAAAA+LGJ9AAAgAElEQVR4nO2dXWsc2Z2H81X8CUKom4 
