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)
进行内存释放。