从动态内存池的API,我们发现一个特别的变量类型memp_t
void memp_init(void);
void *memp_malloc(memp_t type);
void memp_free(memp_t type, void *mem);
关于memp_t定义很有趣,在枚举体里面加了个头文件,这就需要我们来展开头文件了
typedef enum {
#define LWIP_MEMPOOL(name,num,size,desc) MEMP_##name,
#include "lwip/priv/memp_std.h"
MEMP_MAX
} memp_t;
展开后得到
typedef enum {
#define LWIP_MEMPOOL(name,num,size,desc) MEMP_##name,
......
#if LWIP_RAW
LWIP_MEMPOOL(RAW_PCB, MEMP_NUM_RAW_PCB, sizeof(struct raw_pcb), "RAW_PCB")
#endif
#if LWIP_UDP
LWIP_MEMPOOL(UDP_PCB, MEMP_NUM_UDP_PCB, sizeof(struct udp_pcb), "UDP_PCB")
#endif
#if LWIP_TCP
LWIP_MEMPOOL(TCP_PCB, MEMP_NUM_TCP_PCB, sizeof(struct tcp_pcb), "TCP_PCB")
LWIP_MEMPOOL(TCP_PCB_LISTEN, MEMP_NUM_TCP_PCB_LISTEN, sizeof(struct tcp_pcb_listen), "TCP_PCB_LISTEN")
LWIP_MEMPOOL(TCP_SEG, MEMP_NUM_TCP_SEG, sizeof(struct tcp_seg), "TCP_SEG")
#endif
......
#undef LWIP_MEMPOOL
......
MEMP_MAX
} memp_t;
进一步,对宏LWIP_MEMPOOL进行展开,得到
typedef enum {
MEMP_RAW_PCB,
MEMP_UDP_PCB,
MEMP_TCP_PCB,
MEMP_TCP_PCB_LISTEN,
MEMP_TCP_SEG,
......
MEMP_MAX
} memp_t;
这实际上枚举了内存池的类型。
接下来,分析memp.c文件
首先来看,LWIP_MEMPOOL_DECLARE,这又是一个很有意思的宏定义
#define LWIP_MEMPOOL(name,num,size,desc) LWIP_MEMPOOL_DECLARE(name,num,size,desc)
#include "lwip/priv/memp_std.h"
首先对#include "lwip/priv/memp_std.h"进行展开
#define LWIP_MEMPOOL(name,num,size,desc) LWIP_MEMPOOL_DECLARE(name,num,size,desc)
......
#if LWIP_RAW
LWIP_MEMPOOL(RAW_PCB, MEMP_NUM_RAW_PCB, sizeof(struct raw_pcb), "RAW_PCB")
#endif
#if LWIP_UDP
LWIP_MEMPOOL(UDP_PCB, MEMP_NUM_UDP_PCB, sizeof(struct udp_pcb), "UDP_PCB")
#endif
#if LWIP_TCP
LWIP_MEMPOOL(TCP_PCB, MEMP_NUM_TCP_PCB, sizeof(struct tcp_pcb), "TCP_PCB")
LWIP_MEMPOOL(TCP_PCB_LISTEN, MEMP_NUM_TCP_PCB_LISTEN, sizeof(struct tcp_pcb_listen), "TCP_PCB_LISTEN")
LWIP_MEMPOOL(TCP_SEG, MEMP_NUM_TCP_SEG, sizeof(struct tcp_seg), "TCP_SEG")
#endif
......
#undef LWIP_MEMPOOL
继续对LWIP_MEMPOOL进行展开
......
#if LWIP_RAW
LWIP_MEMPOOL_DECLARE(RAW_PCB, MEMP_NUM_RAW_PCB, sizeof(struct raw_pcb), "RAW_PCB")
#endif
#if LWIP_UDP
LWIP_MEMPOOL_DECLARE(UDP_PCB, MEMP_NUM_UDP_PCB, sizeof(struct udp_pcb), "UDP_PCB")
#endif
#if LWIP_TCP
LWIP_MEMPOOL_DECLARE(TCP_PCB, MEMP_NUM_TCP_PCB, sizeof(struct tcp_pcb), "TCP_PCB")
LWIP_MEMPOOL_DECLARE(TCP_PCB_LISTEN, MEMP_NUM_TCP_PCB_LISTEN, sizeof(struct tcp_pcb_listen), "TCP_PCB_LISTEN")
LWIP_MEMPOOL_DECLARE(TCP_SEG, MEMP_NUM_TCP_SEG, sizeof(struct tcp_seg), "TCP_SEG")
#endif
......
继续对LWIP_MEMPOOL_DECLARE进行展开,以RAW_PCB为例
u8_t memp_memory_RAW_PCB_base[MEMP_NUM_RAW_PCB * sizeof(struct raw_pcb)];
static struct stats_mem memp_stats_RAW_PCB;
static struct memp *memp_tab_RAW_PCB;
const struct memp_desc memp_RAW_PCB =
{
"RAW_PCB",
&memp_stats_RAW_PCB,
sizeof(struct raw_pcb),
MEMP_NUM_RAW_PCB,
memp_memory_RAW_PCB_base,
&memp_tab_RAW_PCB
};
结构体struct memp_desc是对内存池的一个描述,
struct memp_desc
{
const char *desc; //字符串描述
struct stats_mem *stats; //内存池状态
u16_t size; //内存池单元大小
u16_t num; //内存池单元数
u8_t *base; //内存池首地址
struct memp **tab; //内存池第一个空闲单元地址
}
继续来看,memp_pools,这是一个内存描述数组
const struct memp_desc *const memp_pools[MEMP_MAX] = {
#define LWIP_MEMPOOL(name,num,size,desc) &memp_ ## name,
#include "lwip/priv/memp_std.h"
};
对#include "lwip/priv/memp_std.h"和LWIP_MEMPOOL分别进行展开
const struct memp_desc *const memp_pools[MEMP_MAX] = {
&memp_RAW_PCB,
&memp_UDP_PCB,
&memp_TCP_PCB,
&memp_TCP_PCB_LISTEN,
&memp_TCP_SEG,
......
};
这样就将memp_t和memp_pools串联起来了。memp_t枚举了memp_pools数组的所有下标。
初始化内存池
/* 初始化内存池 */
void memp_init(void)
{
u16_t i;
/* 初始化所有类型的内存池 */
for (i = 0; i < LWIP_ARRAYSIZE(memp_pools); i++)
{
/* 初始化单个类型内存池 */
memp_init_pool(memp_pools[i]);
/* 内存池状态指针 */
#if LWIP_STATS && MEMP_STATS
lwip_stats.memp[i] = memp_pools[i]->stats;
#endif
}
#if MEMP_OVERFLOW_CHECK >= 2
memp_overflow_check_all();
#endif
}
/* 初始化单个类型的内存池 */
void memp_init_pool(const struct memp_desc *desc)
{
#if MEMP_MEM_MALLOC
LWIP_UNUSED_ARG(desc);
#else
int i;
struct memp *memp;
/* 第一个空闲单元地址,先置为空 */
*desc->tab = NULL;
/* 内存池首地址,组织成一个单元 */
memp = (struct memp *)LWIP_MEM_ALIGN(desc->base);
#if MEMP_MEM_INIT
memset(memp, 0, (size_t)desc->num * (MEMP_SIZE + desc->size
#if MEMP_OVERFLOW_CHECK
+ MEM_SANITY_REGION_AFTER_ALIGNED
#endif
));
#endif
/* 将所有内存单元都挂接到空闲单元链表上 */
for (i = 0; i < desc->num; ++i)
{
/* 每一个内存单元都指向上一个内存单元 */
memp->next = *desc->tab;
/* 更新上一个内存单元 */
*desc->tab = memp;
#if MEMP_OVERFLOW_CHECK
memp_overflow_init_element(memp, desc);
#endif
/* 偏移到下一个单元 */
memp = (struct memp *)(void *)((u8_t *)memp + MEMP_SIZE + desc->size
#if MEMP_OVERFLOW_CHECK
+ MEM_SANITY_REGION_AFTER_ALIGNED
#endif
);
}
/* 可用的内存单元数 */
#if MEMP_STATS
desc->stats->avail = desc->num;
#endif
#endif
/* 内存池名字 */
#if MEMP_STATS && (defined(LWIP_DEBUG) || LWIP_STATS_DISPLAY)
desc->stats->name = desc->desc;
#endif
}
申请内存池单元
/* 申请一个内存池单元 */
void *
#if !MEMP_OVERFLOW_CHECK
memp_malloc(memp_t type)
#else
memp_malloc_fn(memp_t type, const char *file, const int line)
#endif
{
void *memp;
LWIP_ERROR("memp_malloc: type < MEMP_MAX", (type < MEMP_MAX), return NULL;);
#if MEMP_OVERFLOW_CHECK >= 2
memp_overflow_check_all();
#endif
/* 申请单个类型的内存池单元 */
#if !MEMP_OVERFLOW_CHECK
memp = do_memp_malloc_pool(memp_pools[type]);
#else
memp = do_memp_malloc_pool_fn(memp_pools[type], file, line);
#endif
return memp;
}
/* 申请单个类型内存池单元 */
static void *
#if !MEMP_OVERFLOW_CHECK
do_memp_malloc_pool(const struct memp_desc *desc)
#else
do_memp_malloc_pool_fn(const struct memp_desc *desc, const char *file, const int line)
#endif
{
struct memp *memp;
SYS_ARCH_DECL_PROTECT(old_level);
#if MEMP_MEM_MALLOC
memp = (struct memp *)mem_malloc(MEMP_SIZE + MEMP_ALIGN_SIZE(desc->size));
SYS_ARCH_PROTECT(old_level);
#else
SYS_ARCH_PROTECT(old_level);
/* 第一个空闲的内存池单元 */
memp = *desc->tab;
#endif
/* 有可以分配的内存单元 */
if (memp != NULL)
{
#if !MEMP_MEM_MALLOC
#if MEMP_OVERFLOW_CHECK == 1
memp_overflow_check_element(memp, desc);
#endif
/* 将第一个空闲的内存池单元向后偏移 */
*desc->tab = memp->next;
#if MEMP_OVERFLOW_CHECK
memp->next = NULL;
#endif
#endif
#if MEMP_OVERFLOW_CHECK
memp->file = file;
memp->line = line;
#if MEMP_MEM_MALLOC
memp_overflow_init_element(memp, desc);
#endif
#endif
LWIP_ASSERT("memp_malloc: memp properly aligned",
((mem_ptr_t)memp % MEM_ALIGNMENT) == 0);
#if MEMP_STATS
/* 已经被使用的内存单元加一 */
desc->stats->used++;
if (desc->stats->used > desc->stats->max)
{
desc->stats->max = desc->stats->used;
}
#endif
SYS_ARCH_UNPROTECT(old_level);
return ((u8_t *)memp + MEMP_SIZE);
}
/* 已经没有可分配的内存单元 */
else
{
/* 错误次数加一 */
#if MEMP_STATS
desc->stats->err++;
#endif
SYS_ARCH_UNPROTECT(old_level);
LWIP_DEBUGF(MEMP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("memp_malloc: out of memory in pool %s\n", desc->desc));
}
return NULL;
}
释放内存池单元
/* 释放内存池单元 */
void memp_free(memp_t type, void *mem)
{
#ifdef LWIP_HOOK_MEMP_AVAILABLE
struct memp *old_first;
#endif
LWIP_ERROR("memp_free: type < MEMP_MAX", (type < MEMP_MAX), return;);
if (mem == NULL)
{
return;
}
#if MEMP_OVERFLOW_CHECK >= 2
memp_overflow_check_all();
#endif
#ifdef LWIP_HOOK_MEMP_AVAILABLE
old_first = *memp_pools[type]->tab;
#endif
/* 释放单个类型的内存池单元 */
do_memp_free_pool(memp_pools[type], mem);
#ifdef LWIP_HOOK_MEMP_AVAILABLE
if (old_first == NULL) {
LWIP_HOOK_MEMP_AVAILABLE(type);
}
#endif
}