lwip memp(內存池)
內存池聲明過程
內存池聲明宏定義
#define LWIP_MEMPOOL(name,num,size,desc) LWIP_MEMPOOL_DECLARE(name,num,size,desc)
在 #include "lwip/memp.h" 文件中進行定義
/**
* @ingroup mempool
* Declare a private memory pool
* Private mempools example:
* .h: only when pool is used in multiple .c files: LWIP_MEMPOOL_PROTOTYPE(my_private_pool);
* .c:
* - in global variables section: LWIP_MEMPOOL_DECLARE(my_private_pool, 10, sizeof(foo), "Some description")
* - call ONCE before using pool (e.g. in some init() function): LWIP_MEMPOOL_INIT(my_private_pool);
* - allocate: void* my_new_mem = LWIP_MEMPOOL_ALLOC(my_private_pool);
* - free: LWIP_MEMPOOL_FREE(my_private_pool, my_new_mem);
*
* To relocate a pool, declare it as extern in cc.h. Example for GCC:
* extern u8_t \_\_attribute\_\_((section(".onchip_mem"))) memp_memory_my_private_pool_base[];
*/
#define LWIP_MEMPOOL_DECLARE(name,num,size,desc) \
//聲明內存空間
LWIP_DECLARE_MEMORY_ALIGNED(memp_memory_ ## name ## _base, ((num) * (MEMP_SIZE + MEMP_ALIGN_SIZE(size)))); \
\
//聲明內存統計數據實例
//#define LWIP_MEMPOOL_DECLARE_STATS_INSTANCE(name) static struct stats_mem name;
LWIP_MEMPOOL_DECLARE_STATS_INSTANCE(memp_stats_ ## name) \
\
//聲明內存池表
static struct memp *memp_tab_ ## name; \
\
//聲明內存池描述結構體
//一類內存池對應一種描述結構體
const struct memp_desc memp_ ## name = { \
DECLARE_LWIP_MEMPOOL_DESC(desc) \
LWIP_MEMPOOL_DECLARE_STATS_REFERENCE(memp_stats_ ## name) \
LWIP_MEM_ALIGN_SIZE(size), \
(num), \
memp_memory_ ## name ## _base, \
&memp_tab_ ## name \
};
聲明內存統計數據實例
/** Memory stats */
struct stats_mem {
#if defined(LWIP_DEBUG) || LWIP_STATS_DISPLAY
const char *name;
#endif /* defined(LWIP_DEBUG) || LWIP_STATS_DISPLAY */
STAT_COUNTER err;
mem_size_t avail; //有效元素數量
mem_size_t used; //已用元素數量
mem_size_t max; //最大元素數量
STAT_COUNTER illegal;
};
內存池結構體
struct memp {
struct memp *next;
#if MEMP_OVERFLOW_CHECK
const char *file;
int line;
#endif /* MEMP_OVERFLOW_CHECK */
};
內存池描述結構體
/** Memory pool descriptor */
struct memp_desc {
#if defined(LWIP_DEBUG) || MEMP_OVERFLOW_CHECK || LWIP_STATS_DISPLAY
/** Textual description */
const char *desc; //內存池描述字符
#endif /* LWIP_DEBUG || MEMP_OVERFLOW_CHECK || LWIP_STATS_DISPLAY */
#if MEMP_STATS
/** Statistics */
struct stats_mem *stats; //內存狀態統計
#endif
/** Element size */
u16_t size; //元素大小
#if !MEMP_MEM_MALLOC
/** Number of elements */
u16_t num; //元素數量
/** Base address */
u8_t *base; //內存池基地址
/** First free element of each pool. Elements form a linked list. */
struct memp **tab; //空閒元素首指針
#endif /* MEMP_MEM_MALLOC */
};
內存池聲明示例:
所有使用到的內存池在#include "lwip/priv/memp_std.h"
文件中進行聲明,實際使用了全局變量作爲內存池的空間。
以LWIP_MEMPOOL(TCP_SEG, MEMP_NUM_TCP_SEG, sizeof(struct tcp_seg), "TCP_SEG")
爲例說明內存池分配
的過程。
LWIP_MEMPOOL_DECLARE
宏的展開爲
LWIP_MEMPOOL_DECLARE(name,num,size,desc)
LWIP_MEMPOOL_DECLARE(TCP_SEG, MEMP_NUM_TCP_SEG, sizeof(struct tcp_seg), "TCP_SEG") \
//聲明內存空間
LWIP_DECLARE_MEMORY_ALIGNED(memp_memory_TCP_SEG_base, ((MEMP_NUM_TCP_SEG) * (MEMP_SIZE + MEMP_ALIGN_SIZE(sizeof(struct tcp_seg))))); \
\
//聲明內存統計數據實例
LWIP_MEMPOOL_DECLARE_STATS_INSTANCE(memp_stats_TCP_SEG) \
\
//聲明內存池表
static struct memp *memp_tab_TCP_SEG; \
\
//聲明內存池描述結構體
//一類內存池對應一種描述結構體
const struct memp_desc memp_TCP_SEG = { \
DECLARE_LWIP_MEMPOOL_DESC("TCP_SEG") \
LWIP_MEMPOOL_DECLARE_STATS_REFERENCE(memp_stats_TCP_SEG) \
LWIP_MEM_ALIGN_SIZE(sizeof(struct tcp_seg)), \
(MEMP_NUM_TCP_SEG), \
memp_memory_TCP_SEG_base, \
&memp_tab_TCP_SEG \
};
以上使用宏定義,定義對應的內存池內存空間。
LWIP_DECLARE_MEMORY_ALIGNED
宏用於定義內存空間,其定義如下:
/** Allocates a memory buffer of specified size that is of sufficient size to align
* its start address using LWIP_MEM_ALIGN.
* You can declare your own version here e.g. to enforce alignment without adding
* trailing padding bytes (see LWIP_MEM_ALIGN_BUFFER) or your own section placement
* requirements.\n
* e.g. if you use gcc and need 32 bit alignment:\n
* \#define LWIP_DECLARE_MEMORY_ALIGNED(variable_name, size) u8_t variable_name[size] \_\_attribute\_\_((aligned(4)))\n
* or more portable:\n
* \#define LWIP_DECLARE_MEMORY_ALIGNED(variable_name, size) u32_t variable_name[(size + sizeof(u32_t) - 1) / sizeof(u32_t)]
*/
#ifndef LWIP_DECLARE_MEMORY_ALIGNED
#define LWIP_DECLARE_MEMORY_ALIGNED(variable_name, size) u8_t variable_name[LWIP_MEM_ALIGN_BUFFER(size)]
#endif
使用memp_memory_TCP_SEG_base
作爲數組的名稱,數組大小爲((MEMP_NUM_TCP_SEG) * (MEMP_SIZE + MEMP_ALIGN_SIZE(sizeof(struct tcp_seg))))
字節。
定義的內存空間,可以在編譯生成的.map
文件中查到:
memp_memory_TCP_SEG_base 0x6800b550 Data 20003 memp.o(.bss)
LWIP_MEMPOOL_DECLARE_STATS_INSTANCE
宏用於聲明內存池統計結構體。
memp.c
文件的開頭部分,有如下兩個宏定義的地方
#define LWIP_MEMPOOL(name,num,size,desc) LWIP_MEMPOOL_DECLARE(name,num,size,desc)
#include "lwip/priv/memp_std.h"
const struct memp_desc *const memp_pools[MEMP_MAX] = {
#define LWIP_MEMPOOL(name,num,size,desc) &memp_ ## name,
#include "lwip/priv/memp_std.h"
};
通過兩次定義宏LWIP_MEMPOOL
,巧妙地構建所有的內存池空間。
第一次定義LWIP_MEMPOOL
宏爲LWIP_MEMPOOL_DECLARE
,然後再把lwip/priv/memp_std.h
文件的內存包括進行。
會進入lwip/priv/memp_std.h
文件,對每個宏定義LWIP_MEMPOOL(TCP_SEG, MEMP_NUM_TCP_SEG, sizeof(struct tcp_seg), "TCP_SEG")
對每個宏定義用LWIP_MEMPOOL_DECLARE
進行展開,分包聲明結構體和內存空間。
第二次定義LWIP_MEMPOOL
宏爲&memp_ ## name
,在memp_pools
指針數組中。
在LWIP_MEMPOOL
宏定義下面,包含了"lwip/priv/memp_std.h"
文件。
因此會再次進入該文件,使用新的&memp_ ## name
宏對文件下的每個項進行定義。
第一次調用LWIP_MEMPOOL
宏時,創建以const struct memp_desc memp_ ## name
命令的結構體,
第二次調用LWIP_MEMPOOL
宏時,對該結構體進行引用。
使用memp_pools
數組,對所有的內存池進行統一管理。
內存池使用
內存池使用之前,首先調用memp_init()
對memp_pools
數組進行初始化處理。
調用memp_init_pool(const struct memp_desc *desc)
函數,對具體內初池進行初始化。
主要是對齊內存池首地址、清空內存池空間、構建內存池鏈表、初始化內存統計結構體。
使用分配時,調用memp_malloc(memp_t type)
函數,傳入需要分配的內存池類型。
調用do_memp_malloc_pool(const struct memp_desc *desc)
進行實際內存分配。
使用過後,調用memp_free(memp_t type, void *mem)
進行內存釋放。