LwIP中的内存管理
LwIP中的有两种方式的内存,heap和pool。老衲五木的《LwIP协议栈源码详解》将heap称之为动态内存堆,将pool称为动态内存池。
heap像是一块蛋糕,分配的时候容易产生碎片,因为你只能看,看完之后还得还回去,当等待切的人多了并且大小不一定时,容易产生很多细小的碎片,当你需要切一块较大的蛋糕时,发现没有符合你需要的蛋糕块,因此内存申请频频失败。
pool是对一整块蛋糕进行均分,进行统一大小的分配。如果你使用的数据小于蛋糕的容量,那也只好使用它。如果大于一块蛋糕的容量,就得多申请一块或者更多。有个问题就是pool蛋糕的均分,分的太小容易,内存利用率降低;切得太大,内存严重浪费。
Pool型一般用于从链路层就收一个帧,目的是快速、少碎片、浪费一点没关系。(prevents fragmentation and is much faster than
* a heap but might waste some memory)
Heap型一般用于缓存应用层生成的数据,大小自己定,相切多少切多少,随心所欲,尽管以后可能没得切,但我只在乎现在,也许以后就有新的方法解决呢。
LwIP内存分配有三种方法:
1.C库自带的内存分配策略
2.动态内存堆(Heap)分配策略
3.动态内存池(Pool)分配策略
在配置时,有两个文件opt.h和lwipopts.h需要关注。“opt.h是lwip“出厂”时原装的配置文件,lwipopts.h集合了opt.h中常常需要改动的部分和针对ST所特有的配置选项添加进来了。这两个文件里边都配置的选项,以后者为准,不是共有的选项以它们各自的配置为准。”
在opt.h中,有如下片段
------------------------------------
---------- Memory options ----------
------------------------------------
*/
/**
* MEM_LIBC_MALLOC==1: Use malloc/free/realloc provided by your C-library
* instead of the lwip internal allocator. Can save code size if you
* already use it.
*/
#ifndef MEM_LIBC_MALLOC
#define MEM_LIBC_MALLOC 0
#endif
当MEM_LIBC_MALLOC定义为1时,使用C库自带的内存分配策略,而为0时,使用LwIP自身的动态分配策略。
而动态内存堆分配策略可以有两种实现方式,“第一种就是如前所述的通过
开辟一个内存堆,然后通过模拟C运行时库的内存分配策略来实现。第二种就是通过动态
内存池的方式来实现,也即动态内存堆分配函数通过简单调用动态内存池(POOL)分配函数
来完成其功能”。如果需要使用Pool分配函数,则需要同时定义MEM_USE_POOLS和MEMP_USE_CUSTOM_POOLS为1.
在opt.h中定义了该值,所以此处不使用第二种通过内存池Pool分配。一般情况下,使用第一种分配策略实现。
/**
* MEM_USE_POOLS==1: Use an alternative to malloc() by allocating from a set
* of memory pools of various sizes. When mem_malloc is called, an element of
* the smallest pool that can provide the length needed is returned.
* To use this, MEMP_USE_CUSTOM_POOLS also has to be enabled.
*/
#ifndef MEM_USE_POOLS
#define MEM_USE_POOLS 0
#endif
/**
* MEMP_USE_CUSTOM_POOLS==1: whether to include a user file lwippools.h
* that defines additional pools beyond the "standard" ones required
* by lwIP. If you set this to 1, you must have lwippools.h in your
* inlude path somewhere.
*/
#ifndef MEMP_USE_CUSTOM_POOLS
#define MEMP_USE_CUSTOM_POOLS 0
#endif
第一种内存分配管理有最小大小的限制,要求请求的分配大小不能小于MIN_SIZE。MIN_SIZE在Mem.c中定义,如下所示:
/** All allocated blocks will be MIN_SIZE bytes big, at least!
* MIN_SIZE can be overridden to suit your needs. Smaller values save space,
* larger values could prevent too small blocks to fragment the RAM too much. */
#ifndef MIN_SIZE
#define MIN_SIZE 12
#endif /* MIN_SIZE */
在LwIP初始化函数中,LwIP( )调用mem_init( )
/* Zero the heap and initialize start, end and lowest-free*/
void mem_init(void){
struct mem *mem;
... ...
}
/**
* The heap is made up as a list of structs of this type.
* This does not have to be aligned since for getting its size,
* we only use the macro SIZEOF_STRUCT_MEM, which automatically alignes.
*/
struct mem {
/** index (-> ram[next]) of the next struct */
mem_size_t next;
/** index (-> ram[next]) of the next struct */
mem_size_t prev;
/** 1: this area is used; 0: this area is unused */
u8_t used;
};
以上写的参考了http://bbs.eeworld.com.cn/thread-212023-1-3.html和老衲五木的《LwIP协议栈源码详解》。先到这里吧。