http://lwip.wikia.com/wiki/Lwipopts.hhtml
/** * 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_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. defines additional pools */ #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
-------------------------------------------------------------------------------------------------------------
MEM_LIBC_MALLOC == 1 : the standard C library : 程序員
HEAP 數組
malloc(), realloc(), calloc(), free() 緩存
-------------------------------------------------------------------------------------------------------------
MEM_LIBC_MALLOC == 0, MEM_USE_POOLS == 0 : lwIP replacement for your libc malloc() : 安全
u8_t ram_heap[MEM_SIZE_ALIGNED + (2*SIZEOF_STRUCT_MEM) + MEM_ALIGNMENT];app
mem_init(), mem_malloc(), mem_calloc(), mem_free(), mem_trim()less
-------------------------------------------------------------------------------------------------------------
MEM_LIBC_MALLOC == 0, MEM_USE_POOLS == 1 : lwIP head implemented with different sized poolstcp
/** This is the actual memory used by the pools (all pools in one big block). */
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"
];ide
mem_malloc(), mem_free() --> memp_malloc(), memp_free() in memp.c函數
memp_std.h :
/* * Allow for user-defined pools; this must be explicitly set in lwipopts.h * since the default is to NOT look for lwippools.h */ #if MEMP_USE_CUSTOM_POOLS #include "lwippools.h" #endif /* MEMP_USE_CUSTOM_POOLS */
lwippools.h
/* Define three pools with sizes 256, 512, and 1512 bytes */ LWIP_MALLOC_MEMPOOL_START LWIP_MALLOC_MEMPOOL(20, 256) LWIP_MALLOC_MEMPOOL(10, 512) LWIP_MALLOC_MEMPOOL(5, 1512) LWIP_MALLOC_MEMPOOL_END /* My sys_arch uses memory pools to allocate mbox and sems */ LWIP_MEMPOOL(SYS_MBOX, 22, sizeof(struct sys_mbox_struct), "SYS_MBOX") LWIP_MEMPOOL(SYS_SEM, 12, sizeof(struct sys_sem_struct), "SYS_SEM")
In an embedded environment, memory pools make for fast and efficient memory allocation.
lwIP provides a flexible way to manage memory pool sizes and organization.
lwIP reserves a fixed-size static chunk of memory in the data segment,
which is subdivided into the various pools that lwip uses for the various data structures.
For example, there is a pool just for struct tcp_pcb
's, and another pool just for struct udp_pcb
's.
Each pool can be configured to hold a fixed number of data structures;
this number can be changed in the lwipopts.h file by changing the variousMEMP_NUM_*
values.
For example, MEMP_NUM_TCP_PCB
and MEMP_NUM_UDP_PCB
control the maximum number of tcp_pcb
and udb_pcb
structures
that can be active in the system at any given time.
It is also possible to create custom memory pools in addition to the standard ones provided by lwIP.
lwIP uses a custom function mem_malloc
for all dynamic allocation; therefore, it is easy to change how lwIP uses its RAM.
There are three possibilities provided out-of-the-box:
mem_malloc
. [static array ram_heap]MEM_SIZE
to change the size of the lwIP heap.malloc
and free
. [ alloc from HEAP ]MEM_LIBC_MALLOC
.mem_malloc [static array memp_memory]
MEM_USE_POOLS
and MEMP_USE_CUSTOM_POOLS
and a new custom file lwippools.h
.lwIP uses memory for:
Unless you use a C library heap implementation (by defining MEM_LIBC_MALLOC to 1), dynamically allocated memory must be statically allocated somewhere.
This means you reserve a specific amount of memory for the heap or the memp pools from which the code dynamically allocates memory at runtime.
If you then even define MEM_LIBC_MALLOC to 1, too, lwIP doesn't need extra memory for dynamically allocated memory but only uses the C library heap instead.
However, you then have to make sure that this heap is big enough to run your application.
The size of this heap and memp pools can be adjusted to save RAM:
However, if you define MEMP_MEM_MALLOC to 1 in your lwipopts.h,
*every* piece of dynamically allocated memory will come from the *heap* (the size of which is defined by MEM_SIZE).
-- this is the *heap* and it is allocated as mem_memory.
To tweak the various MEMP_NUM_ defines, define LWIP_STATS=1 and LWIP_STATS_DISPLAY=1 and
call stats_display() to see how many entries of each pool are used (or have a look at the global variable lwip_stats instead).
lwIP provides a way to define your own custom memory pools to be used in addition to the standard ones provided by lwIP.
There are two reasons you may need to do this:
mem_malloc
, as described in the next section
The standard memory pools are defined in the memp_std.h
file.
If you define the MEMP_USE_CUSTOM_POOLS
macro, then lwIP will also search for a lwippools.h
file.
This file should be created in the same directory as lwipopts.h
and only needs to contain additional pools not defined in memp_std.h
.
There are three "kinds" of pools that can be defined:
LWIP_MEMPOOL(pool_name, number_elements, element_size, pool_desc)
. LWIP_PBUF_MEMPOOL(pool_name, number_elements, payload_size, pool_desc)
. pbuf_alloc
.LWIP_MALLOC_MEMPOOL(number_buffers, buffer_size)
. mem_malloc
(see next section).
Simply include a definition in your lwippools.h
file for each additional pool you want to be included in lwIP's memory subsystem.
An example is provided at the end of this chapter.
/* Define three pools with sizes 256, 512, and 1512 bytes */ LWIP_MALLOC_MEMPOOL_START LWIP_MALLOC_MEMPOOL(20, 256) LWIP_MALLOC_MEMPOOL(10, 512) LWIP_MALLOC_MEMPOOL(5, 1512) LWIP_MALLOC_MEMPOOL_END /* My sys_arch uses memory pools to allocate mbox and sems */ LWIP_MEMPOOL(SYS_MBOX, 22, sizeof(struct sys_mbox_struct), "SYS_MBOX") LWIP_MEMPOOL(SYS_SEM, 12, sizeof(struct sys_sem_struct), "SYS_SEM")
mem_malloc
To enable a pool-based mem_malloc
, you must first define a set of chunk sizes.
When lwIP calls mem_malloc for a block of size "x", it will attempt to allocate a chunk of size at least as big as "x".
For example, if your chunk sizes are 256 (for small blocks), 512 (for medium blocks) and 1512 (for full Ethernet frames),
then calling mem_malloc for blocks of size 100, 400, and 1000 will result in a block of each size.
The example below shows how to do this setup.
The definitions for all malloc memory pools must be made contiguously as a single group,
starting with a LWIP_MALLOC_MEMPOOL_START
and ending with a LWIP_MALLOC_MEMPOOL_END
.
WARNING:
The memory pool allocator will pick the first pool size that fits the requested size,
testing them in the order that you list them in the lwippools.h
file.
Therefore, you probably want to list them in order of increasing size!
If the allocation fails, it does not test pools later on in the list.
/* Define three pools with sizes 256, 512, and 1512 bytes */ LWIP_MALLOC_MEMPOOL_START LWIP_MALLOC_MEMPOOL(20, 256) LWIP_MALLOC_MEMPOOL(10, 512) LWIP_MALLOC_MEMPOOL(5, 1512) LWIP_MALLOC_MEMPOOL_END /* My sys_arch uses memory pools to allocate mbox and sems */ LWIP_MEMPOOL(SYS_MBOX, 22, sizeof(struct sys_mbox_struct), "SYS_MBOX") LWIP_MEMPOOL(SYS_SEM, 12, sizeof(struct sys_sem_struct), "SYS_SEM")
.// LWIP_MEMPOOL( pool_name, number_elements, element_size, pool_desc)
This is a lightweight replacement for the standard C library malloc().
If you want to use the standard C library malloc() instead, define MEM_LIBC_MALLOC to 1 in your lwipopts.h
To let mem_malloc() use pools (prevents fragmentation and is much faster than a heap but might waste some memory),
define MEM_USE_POOLS to 1, define MEM_USE_CUSTOM_POOLS to 1 and
create a file "lwippools.h" that includes a list of pools like this (more pools can be added between _START and _END):
* Define three pools with sizes 256, 512, and 1512 bytes
* LWIP_MALLOC_MEMPOOL_START
* LWIP_MALLOC_MEMPOOL(20, 256)
* LWIP_MALLOC_MEMPOOL(10, 512)
* LWIP_MALLOC_MEMPOOL(5, 1512)
* LWIP_MALLOC_MEMPOOL_END
lwIP has dedicated pools for many structures (netconn, protocol control blocks,* packet buffers, ...).
All these pools are managed here.
內存池 (Memory Pool),又被稱爲固定大小區塊規劃 (fixed-size-blocks allocation),
容許程序員以相似 C語言 的 malloc 或是 C++ 的 new 運算對象進行動態的存儲器規劃。
對於其它動態存儲器規劃的實踐來講,由於會變更存儲器區塊大小致使的碎片問題,致使在實時系統上受限於性能所以,
根本沒法使用。內存池'提供了一個更有效率的解決方案:預先規劃必定數量的存儲器區塊,
使得整個程序能夠在運行期規劃 (allocate)、使用 (access)、歸還 (free) 存儲器區塊。
優勢
缺點
http://blog.csdn.net/wjjontheway/article/details/9089729
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庫自帶的內存分配策略 <HEAP> <MEM_LIBC_MALLOC==1>
2.動態內存堆(Heap)分配策略 <Static ARRAY> <MEM_LIBC_MALLOC==1, MEM_USE_POOLS==0
>
3.動態內存池(Pool)分配策略<Static ARRAY> <MEM_LIBC_MALLOC==1, MEM_USE_POOLS==1
>
在配置時,有兩個文件opt.h和lwipopts.h須要關注。
「opt.h是lwip「出廠」時原裝的配置文件,
lwipopts.h集合了opt.h中經常須要改動的部分。
這兩個文件裏邊都配置的選項,之後者爲準,不是共有的選項以它們各自的配置爲準。」
在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庫自帶的內存分配策略,
當MEM_LIBC_MALLOC定義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協議棧源碼詳解》。
http://blog.csdn.net/kaka11/article/details/6198582
由於lwIP主要用於嵌入式系統,內存要求比較高,因此要對那些小對象進行池化之類的處理來加快分配速度,減小內存碎片產生。
lwIP中主要有mem.h, mem.c, memp.h, memp.c, memp_std.h, lwippools.h 幾個類組成了內存管理模塊。
memp.c
動態內存池管理器, lwip擁有各類不一樣的內存池來爲各個模塊的小對象分配內存。
一個內存池主要有name,description,number(內存池裏的內存節點的數目)和size(內存池裏的內存節點的大小)
內存節點的struct描述:
struct memp { struct memp *next; // 指向下一個內存節點的指針 #if MEMP_OVERFLOW_CHECK // 若是進行內存溢出檢測, const char *file; // 發生溢出時調用函數的文件名 int line; // 發生溢出時調用函數的行號 #endif /* MEMP_OVERFLOW_CHECK */ };
lwip中各種內存池的描述在memp_std.h文件中:
該文件主要由三種內存池組成:
1. LWIP_MEMPOOL(標準的內存池)
2. LWIP_MALLOC_MEMPOOL(被mem.c中mem_malloc使用的內存池,須要在lwippools.h自定義不一樣大小的內存池,稍後會講到)
3. LWIP_PBUF_MEMPOOL(PBUF的內存池)。
其中2,3兩種內存池均是經過調用第一種內存池來實現的,因此咱們來看下第一種內存池,也就是lwip的標準內存池。
咱們來看一個TCP_PCB的內存池定義:
LWIP_MEMPOOL(TCP_PCB, MEMP_NUM_TCP_PCB, sizeof(struct tcp_pcb), "TCP_PCB")
其中TCP_PCB是內存池名稱,
MEMP_NUM_TCP_PCB是節點的數目,
sizeof(struct tcp_pcb)是每一個節點大小,
"TCP_PCB"是內存池的描述。
而在memp.c中經過不判定義這些描述(宏)來保存內存池中各類不一樣的信息到相應的結構中去:
1. 經過各類內存池的惟一的名稱定義一個enum,而且在最後插入MEMP_MAX來獲得內存池的總數。
typedef enum { #define LWIP_MEMPOOL(name,num,size,desc) MEMP_##name, #include "lwip/memp_std.h" MEMP_MAX } memp_t;
2.定義數組memp_size[MEMP_MAX]存放每一個內存池的節點大小。
/** This array holds the element sizes of each pool. */ #if !MEM_USE_POOLS && !MEMP_MEM_MALLOC static #endif const u16_t memp_sizes[MEMP_MAX] = { #define LWIP_MEMPOOL(name,num,size,desc) LWIP_MEM_ALIGN_SIZE(size), #include "lwip/memp_std.h" };
3. 定義數組memp_num[MEMP_MAX]存放每一個內存池的節點數目。
/** This array holds the number of elements in each pool. */ static const u16_t memp_num[MEMP_MAX] = { #define LWIP_MEMPOOL(name,num,size,desc) (num), #include "lwip/memp_std.h" };
4. 定義數組memp_desc[MEMP_MAX]存放每一個內存池的描述。
/** This array holds a textual description of each pool. */ #ifdef LWIP_DEBUG static const char *memp_desc[MEMP_MAX] = { #define LWIP_MEMPOOL(name,num,size,desc) (desc), #include "lwip/memp_std.h" }; #endif /* LWIP_DEBUG */
5. 定義數組memp_memory,這個數組所佔有的內存就是全部內存池用的實際內存塊。
數組長度爲各個池的須要的內存總和,即每一個內存池+ ( (num) * (MEMP_SIZE + MEMP_ALIGN_SIZE(size) ) ),
其中num爲節點數目,MEMP_SIZE爲每一個節點結構所須要的額外內存,size爲內存池提供給上層用戶的內存大小。
這些大小都是要對齊的,還有個MEM_ALIGNMENT - 1是爲了對齊數組memp_memory,
由於定義的memp_memory是不必定對齊的,最壞的狀況就要MEM_ALIGNMENT - 1。
/** This is the actual memory used by the pools. */ 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" ];
內存對齊的概念我想你們都懂,這兒就很少作解釋了,在lwip的mem.h頭文件定義了下面兩個宏來進行size和內存地址的對齊。
#ifndef LWIP_MEM_ALIGN_SIZE #define LWIP_MEM_ALIGN_SIZE(size) (((size) + MEM_ALIGNMENT - 1) & ~(MEM_ALIGNMENT-1)) #endif #ifndef LWIP_MEM_ALIGN #define LWIP_MEM_ALIGN(addr) ((void *)(((mem_ptr_t)(addr) + MEM_ALIGNMENT - 1) & ~(mem_ptr_t)(MEM_ALIGNMENT-1))) #endif
mem.c:
若是使用pool的話就是運用內存池管理器進行內存管理。:: 動態內存池(Pool)分配策略
不然的話主要實現了一個實現了一個相似於C malloc的heap的輕量級內存管理器。:: 動態內存堆(Heap)分配策略
動態內存堆(Heap)分配策略 <Static ARRAY> <MEM_LIBC_MALLOC==1, MEM_USE_POOLS==0
>
動態內存池(Pool)分配策略<Static ARRAY> <MEM_LIBC_MALLOC==1, MEM_USE_POOLS==1
>
下面開始講述每一個函數的功能,工做原理和要點:
memp.h memp.c
memp_init(): 初始化每一個內存池,經過struct memp做爲節點以單鏈表的形式串聯起來。
memp_malloc(): 從相應的內存池中取出內存。
memp_free(): 歸還內存到相應的內存池,須要檢測溢出。
memp_overflow_init(): 溢出檢測的初始化,主要是在用戶申請的內存區域先後插入一些填充符0xcd。
memp_overflow_check_element(): 節點溢出檢測,在用戶申請的內存區域先後檢查填充符0xcd是否被覆蓋,是則溢出。
memp_overflow_check_all(): 全部節點溢出檢測,安全,可是相對慢。
一個內存池的一個結點的內存分配狀況:
------------------------------------------------------------------------------------------------------------------------------------
struct memp所佔用的內存 + check_overflow_before_region + 用戶申請的內存 +check_overflow_after_region
------------------------------------------------------------------------------------------------------------------------------------
memp_memory的內存分配狀況:
------------------------------------------------------------------------------------------------------------------------------------
對齊地址的內存空間(0->MEM_ALIGNMENT - 1) + 各個內存池所佔內存
------------------------------------------------------------------------------------------------------------------------------------
memp_std.h:
防止屢次定義錯誤,由於memp.c使用#include memp_std.h而且定義如下的宏的技巧,因此每次須要undef這些宏.
mem.h mem.c
#if MEM_USE_POOLS:
mem_malloc: 從相應的提供給malloc用的不一樣size的pool中取一個合適的一個,而且將這個pool的size保存到相應的結構memp_malloc_helper中。
能夠在lwippools.h自定義pool,詳情請見代碼memp_std.h和memp.h文件的註釋:
LWIP_MALLOC_MEMPOOL_START
LWIP_MALLOC_MEMPOOL(20, 256)
LWIP_MALLOC_MEMPOOL(10, 512)
LWIP_MALLOC_MEMPOOL(5, 1512)
LWIP_MALLOC_MEMPOOL_END
mem_free: 釋放到相應的內存池中, 取出memp_malloc_helper中的size放入相應的內存池中去。
#else /* MEM_USE_POOLS: */
實現了一個相似於C malloc的heap的輕量級內存管理器。
/* 採用索引雙鏈表的形式來管理heap */ /* 節點結構 */ struct mem { /** index (-> ram[next]) of the next struct */ mem_size_t next; // 下一個struct的索引 /** index (-> ram[next]) of the next struct */ mem_size_t prev; // 上一個struct的索引 /** 1: this area is used; 0: this area is unused */ u8_t used; // 是否被使用 };
mem_init: 初始化heap,而且設置lfree爲最低地址的空閒節點,以加快搜索速度。
mem_malloc: 從heap上分配用戶所需size的內存。從lfree節點開始搜索空閒而且能夠容納SIZEOF_STRUCT_MEM + size的空間,
若是找到這樣的節點mem,則分爲兩種狀況,
若是可容納的空間能夠容納SIZEOF_STRUCT_MEM + size + (SIZEOF_STRUCT_MEM + MIN_SIZE_ALIGNED),則說明能夠新建一個空閒節點,
因而將創建新的空閒節點而且插入到mem和mem->next之間,將mem的used標誌爲1,
不然的話不創建節點,只是設置mem的used標誌爲1。
mem_free: 釋放的時候會改used標誌爲0,表示空閒,而且調用plug_holes()函數來進行先後合併空閒空間。
mem_calloc: 使用mem_malloc申請size×count大小的地址,而且初始化清0所分配的內存。
mem_realloc: 從新分配new_size的內存,lwip目前不支持擴大size的狀況。
若是當前節點後面的那個節點也是free的話,那麼能夠合併多餘剩下的節點和後面的那個free節點。
若是不是空閒的則看看剩餘的空間是否足夠新建一個空閒節點,能則建之,並將其插入到鏈表中去。