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内存管理机制的更多相关文章

  1. 浅谈Linux内存管理机制

    经常遇到一些刚接触Linux的新手会问内存占用怎么那么多?在Linux中经常发现空闲内存很少,似乎所有的内存都被系统占用了,表面感觉是内存不够用了,其实不然.这是Linux内存管理的一个优秀特性,在这 ...

  2. ARC内存管理机制详解

    ARC在OC里面个人感觉又是一个高大上的牛词,在前面Objective-C中的内存管理部分提到了ARC内存管理机制,ARC是Automatic Reference Counting---自动引用计数. ...

  3. 深入了解C#系列:谈谈C#中垃圾回收与内存管理机制

    今天抽空来讨论一下.Net的垃圾回收与内存管理机制,也算是完成上个<WCF分布式开发必备知识>系列后的一次休息吧.以前被别人面试的时候问过我GC工作原理的问题,我现在面试新人的时候偶尔也会 ...

  4. 【Cocos2d-x 3.x】内存管理机制与源码分析

    侯捷先生说过这么一句话 :  源码之前,了无秘密. 要了解Cocos2d-x的内存管理机制,就得阅读源码. 接触Cocos2d-x时, Cocos2d-x的最新版本已经到了3.2的时代,在学习Coco ...

  5. Spark 1.6以后的内存管理机制

     Spark 内部管理机制 Spark的内存管理自从1.6开始改变.老的内存管理实现自自staticMemoryManager类,然而现在它被称之为"legacy". " ...

  6. python的内存管理机制

    先从较浅的层面来说,Python的内存管理机制可以从三个方面来讲 (1)垃圾回收 (2)引用计数 (3)内存池机制 一.垃圾回收: python不像C++,Java等语言一样,他们可以不用事先声明变量 ...

  7. Java虚拟机内存管理机制

    自动内存管理机制 Java虚拟机(JVM)在执行Java程序过程中会把它所管理的内存划分为若干个不同的数据区域.这些区域都有各自的用途,以及创建和销毁的时间,有的区域随着虚拟机进程的启动而存在,有的区 ...

  8. 了解linux内存管理机制(转)

    今天了解了下linux内存管理机制,在这里记录下,原文在这里http://ixdba.blog.51cto.com/2895551/541355 根据自己的理解画了张图: 下面是转载的内容: 一 物理 ...

  9. object-c(oc)内存管理机制详解

    1.内存的创建和释放 让我们以Object-c世界中最最简单的申请内存方式展开,谈谈关于一个对象的生命周期.首先创建一个对象: 1 2 3 //“ClassName”是任何你想写的类名,比如NSStr ...

随机推荐

  1. Kuernetes-设计架构(二)

    Kubernetes设计架构 Kubernetes集群包含有节点代理kubelet和Master组件(APIs,scheduler.etc),一切都基于分布式的存储系统.Kubernetes架构图: ...

  2. 基于jQuery的2048小游戏设计(网页版)

    上周模仿一个2048小游戏,总结一下自己在编写代码的时候遇到的一些坑. 游戏规则:省略,我想大部分人都玩过,不写了 源码地址:https://github.com/xinhua6/2048game.g ...

  3. oracle杀死锁表的进程(转发+合并+自己实践)

    之一: Oracle数据库操作中,我们有时会用到锁表查询以及解锁和kill进程等操作 (1)锁表查询的代码有以下的形式:select count(*) from v$locked_object;sel ...

  4. MSSQL如何查看当前数据库的连接数 【转】

    - [SQL Server]版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明 http://ai51av.blogbus.com/logs/52955622.html   如果我们发布 ...

  5. HI2115软件开发板V150版本AT+NSOST指令

    1. 在HI2115里面,由于内存空间比较大,所以支持UDP发送指令AT+NSOST的分包 ret = sendto(socket, seq_num, data_string, length, msg ...

  6. Windows扩展屏开发总结

    本文来自网易云社区 作者:梁敏 一.多屏设置 在设置-系统-可以点击显示器1和2,可以进行单独设置: "使之成为我的主显示器"可以设置当前显示器是主屏:主屏的选择会决定整个虚拟屏幕 ...

  7. [转][赞]Android开发者必知的开发资源

    英文原文:Bongzimo  翻译: ImportNew-黄小非 随着Android平台市场份额的持续猛增 ,越来越多的开发者开始投入Android应用程序的开发大潮.如果您是一位2013年刚刚入行的 ...

  8. Qt HUD(平显)演示程序绿色版

    把一个黑底白字的程序改成黑底绿字 上对比图,左侧是原本,右侧是仿造,有些地方比例还是有问题 其实这个程序没有啥技术含量,就是画 #include "mainwindow.h" #i ...

  9. 第九篇 Python数据类型之集合

    集合 set 写在最前,必须要会的:1.长度len2.成员运算in和not in3.|合集4.&交集5.-差集6.^对称差集7.==8.父集:>,>= 9.子集:<,< ...

  10. 在阿里云上遇见更好的Oracle(二)

    从上一篇文章的反馈来看,大家还是喜欢八卦多过技术细节,那这一篇继续一些题外话,说说我对“去IOE”的看法. 对同一件事情,参与的没参与的人,讨论起来,都会有各自的立场.所以这里先申明一下,以下内容只是 ...