先看memp_t,这是一个枚举体,定义了所有内存池的类型。
typedef enum {
#define LWIP_MEMPOOL(name,num,size,desc) MEMP_##name,
#include "lwip/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进行展开,最终得到memp_t类型如下
typedef enum {
MEMP_RAW_PCB,
MEMP_UDP_PCB,
MEMP_TCP_PCB,
MEMP_TCP_PCB_LISTEN,
MEMP_TCP_SEG,
......
MEMP_MAX
} memp_t;
按照上面的原理,编译的时候,会建立起来几个全局变量
/* 各个内存池单元大小 */
const u16_t memp_sizes[MEMP_MAX] = {
#define LWIP_MEMPOOL(name,num,size,desc) LWIP_MEM_ALIGN_SIZE(size),
#include "lwip/memp_std.h"
};
展开后
const u16_t memp_sizes[MEMP_MAX] = {
LWIP_MEM_ALIGN_SIZE(sizeof(struct raw_pcb)),
LWIP_MEM_ALIGN_SIZE(sizeof(struct udp_pcb)),
LWIP_MEM_ALIGN_SIZE(sizeof(struct tcp_pcb)),
LWIP_MEM_ALIGN_SIZE(sizeof(struct tcp_pcb_listen)),
LWIP_MEM_ALIGN_SIZE(sizeof(struct tcp_seg)),
...
};
/* 各个内存池单元个数数组 */
static const u16_t memp_num[MEMP_MAX] = {
#define LWIP_MEMPOOL(name,num,size,desc) (num),
#include "lwip/memp_std.h"
};
展开后
static const u16_t memp_num[MEMP_MAX] = {
MEMP_NUM_RAW_PCB,
MEMP_NUM_UDP_PCB,
MEMP_NUM_TCP_PCB,
MEMP_NUM_TCP_PCB_LISTEN,
MEMP_NUM_TCP_SEG,
...
};
/* 所有内存池空间 */
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"
];
展开后
static u8_t memp_memory[MEM_ALIGNMENT - 1
+ (MEMP_NUM_RAW_PCB) * (MEMP_SIZE + MEMP_ALIGN_SIZE(sizeof(struct raw_pcb)))
+ (MEMP_NUM_UDP_PCB) * (MEMP_SIZE + MEMP_ALIGN_SIZE(sizeof(struct udp_pcb)))
+ (MEMP_NUM_TCP_PCB) * (MEMP_SIZE + MEMP_ALIGN_SIZE(sizeof(struct tcp_pcb)))
+ (MEMP_NUM_TCP_PCB_LISTEN) * (MEMP_SIZE + MEMP_ALIGN_SIZE(sizeof(struct tcp_pcb_listen)))
+ (MEMP_NUM_TCP_SEG) * (MEMP_SIZE + MEMP_ALIGN_SIZE(sizeof(struct tcp_seg)))
];
接下来再看一个结构体,这个结构体用于将内存池单元连接成链表
/* 内存池单元结构体 */
struct memp {
struct memp *next;
};
而下面这个数组用于指向各个内存池链表中的第一个空闲单元
static struct memp *memp_tab[MEMP_MAX];
接下来看一下内存池相关的API
/* 初始化内存池 */
void memp_init(void)
{
struct memp *memp;
u16_t i, j;
/* 内存池所在内存地址 */
memp = LWIP_MEM_ALIGN(memp_memory);
/* 将内存分割成各个内存池 */
for (i = 0; i < MEMP_MAX; ++i) {
/* 将各个内存池单元连接成链表 */
memp_tab[i] = NULL;
for (j = 0; j < memp_num[i]; ++j) {
memp->next = memp_tab[i];
memp_tab[i] = memp;
memp = (struct memp *)((u8_t *)memp + MEMP_SIZE + memp_sizes[i]);
}
}
}
初始化完成之后,内存池空间被组织成如下结构
/* 申请一个内存池单元 */
void *memp_malloc(memp_t type)
{
struct memp *memp;
/* 内存池空闲单元指针 */
memp = memp_tab[type];
/* 链表头部取出一个单元 */
if (memp != NULL) {
memp_tab[type] = memp->next;
memp = (struct memp *)((u8_t *)memp + MEMP_SIZE);
}
/* 返回内存地址 */
return memp;
}
/* 释放一个内存池单元 */
void memp_free(memp_t type, void *mem)
{
struct memp *memp;
if (mem == NULL) {
return;
}
/* 将内存地址转换为内存池单元指针 */
memp = (struct memp *)((u8_t*)mem - MEMP_SIZE);
/* 将内存池单元插入相应链表头部 */
memp->next = memp_tab[type];
memp_tab[type] = memp;
}