1、C library内存管理
c库自带内存分配和释放函数malloc和free:
void *malloc(long NumBytes):该函数分配了NumBytes个字节,并返回了指向这块内存的指针。如果分配失败,则返回一个空指针(NULL)。
void free(void *FirstByte): 该函数是将之前用malloc分配的空间还给程序或者是操作系统,也就是释放了这块内存,让它重新得到自由。
2、lwip内存池管理
1)相关宏定义
(a)内存策略宏开关
//使用C library中函数malloc和free实现内存堆分配和释放
MEM_LIBC_MALLOC==1
//使用lwip内存堆分配策略实现内存池分配
MEMP_MEM_MALLOC==1
//使用lwip内存池分配策略实现内存堆的分配,需额外定义新的内存池
MEM_USE_POOLS==1
MEMP_USE_CUSTOM_POOLS==1
MEM_USE_POOLS_TRY_BIGGER_POOL==1
//新内存池定义格式如下:
/* 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
*/
(b)内存字节、地址对齐宏定义
#define MEM_ALIGNMENT 4 /*cpu alignment*/
//(e.g. LWIP_MEM_ALIGN_SIZE(3) and LWIP_MEM_ALIGN_SIZE(4) will both yield 4 for MEM_ALIGNMENT == 4)
#define LWIP_MEM_ALIGN_SIZE(size)
(((size) + MEM_ALIGNMENT - 1) & ~(MEM_ALIGNMENT-1))
// (e.g. if buffer is u8_t[] and actual data will be u32_t*)
#define LWIP_MEM_ALIGN_BUFFER(size)
(((size) + MEM_ALIGNMENT - 1))
// ADDR % MEM_ALIGNMENT == 0
#define LWIP_MEM_ALIGN(addr)
((void *)(((mem_ptr_t)(addr) + MEM_ALIGNMENT - 1) &
~(mem_ptr_t)(MEM_ALIGNMENT-1)))
(c)内存池全局变量声明
#define MEMP_SIZE 0
#define MEMP_ALIGN_SIZE(x) (LWIP_MEM_ALIGN_SIZE(x))
/** This array holds the first free element of each pool. Elements form a linked list. */
static struct memp *memp_tab[MEMP_MAX];
//不同类型内存池的大小
static const u16_t memp_sizes[MEMP_MAX] = {
#define LWIP_MEMPOOL(name,num,size,desc) LWIP_MEM_ALIGN_SIZE(size),
#include "lwip/memp_std.h"
};
//不同类型内存池的数量
static const u16_t memp_num[MEMP_MAX] = {
#define LWIP_MEMPOOL(name,num,size,desc) (num),
#include "lwip/memp_std.h"
};
//调试专用描述符
static const char *memp_desc[MEMP_MAX] = {
#define LWIP_MEMPOOL(name,num,size,desc) (desc),
#include "lwip/memp_std.h"
};
//定义内存池数组,开辟静态内存空间
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"
(d)未用到功能的宏设置
#define MEMP_STATS 0
#define MEMP_SEPARATE_POOLS 0
#define MEMP_OVERFLOW_CHECK 0
#define MEMP_SANITY_CHECK 0
2)内存池实现
(a)结构体声明
//内存池类型枚举
typedef enum {
#define LWIP_MEMPOOL(name,num,size,desc) MEMP_##name,
#include "lwip/memp_std.h"
MEMP_MAX
} memp_t;
//内存池操作结构体
struct memp {
struct memp *next;
};
(b)各种类型内存池数量及其大小的定义(部分)
LWIP_MEMPOOL(RAW_PCB,MEMP_NUM_RAW_PCB,
sizeof(struct raw_pcb), "RAW_PCB")
LWIP_MEMPOOL(UDP_PCB, MEMP_NUM_UDP_PCB,
sizeof(struct udp_pcb), "UDP_PCB")
LWIP_MEMPOOL(TCP_PCB,MEMP_NUM_TCP_PCB,
sizeof(struct tcp_pcb), "TCP_PCB")
#define LWIP_PBUF_MEMPOOL(name, num, payload, desc) LWIP_MEMPOOL(name, num, MEMP_ALIGN_SIZE(sizeof(struct pbuf)) + MEMP_ALIGN_SIZE(payload)), desc)
LWIP_PBUF_MEMPOOL(PBUF, MEMP_NUM_PBUF, 0, "PBUF_REF/ROM")
LWIP_PBUF_MEMPOOL(PBUF_POOL,PBUF_POOL_SIZE,
PBUF_POOL_BUFSIZE,"PBUF_POOL")
(c)内存池初始化memp_init
初始化内存池结构示意图

void memp_init(void)
{
struct memp *memp;
u16_t i, j;
memp = (struct memp *)LWIP_MEM_ALIGN(memp_memory);
/* for every pool: */
for (i = 0; i < MEMP_MAX; ++i) {
memp_tab[i] = NULL;
/* create a linked list of memp elements */
for (j = 0; j < memp_num[i]; ++j) {
memp->next = memp_tab[i];
memp_tab[i] = memp;
memp = (struct memp *)(void *)((u8_t *)memp + MEMP_SIZE + memp_sizes[i]);
}
}
}
(d)内存池分配memp_malloc
void *memp_malloc(memp_t type)
{
struct memp *memp;
SYS_ARCH_DECL_PROTECT(old_level);
SYS_ARCH_PROTECT(old_level);
memp = memp_tab[type];
//申请一个type类型的内存池
if (memp != NULL) {
memp_tab[type] = memp->next;
memp = (struct memp*)(void *)((u8_t*)memp + MEMP_SIZE);
}
else {
MEMP_STATS_INC(err, type);
}
SYS_ARCH_UNPROTECT(old_level);
return memp;
}
(e)内存池释放memp_free
void memp_free(memp_t type, void *mem)
{
struct memp *memp;
SYS_ARCH_DECL_PROTECT(old_level);
if (mem == NULL) {
return;
}
memp = (struct memp *)(void *)((u8_t*)mem - MEMP_SIZE);
SYS_ARCH_PROTECT(old_level);
MEMP_STATS_DEC(used, type);
//切换表头
memp->next = memp_tab[type];
memp_tab[type] = memp;
SYS_ARCH_UNPROTECT(old_level);
}
3、lwip内存堆管理
1)、miscellaneous声明
//内存堆管理结构体
struct mem {
mem_size_t next; //字节索引号
mem_size_t prev;
u8_t used;
};
//mem_size_t声明
#if MEM_SIZE > 64000L
typedef u32_t mem_size_t;
#define MEM_SIZE_F U32_F
#else
typedef u16_t mem_size_t;
#define MEM_SIZE_F U16_F
#endif /* MEM_SIZE > 64000 */
//自定义最小、最大申请内存大小
#define MIN_SIZE 12
#define MEM_SIZE (10*1024)
//对齐声明
#define MIN_SIZE_ALIGNED LWIP_MEM_ALIGN_SIZE(MIN_SIZE)
#define SIZEOF_STRUCT_MEM
LWIP_MEM_ALIGN_SIZE(sizeof(struct mem))
#define MEM_SIZE_ALIGNED LWIP_MEM_ALIGN_SIZE(MEM_SIZE)
//全局变量声明,静态数组声明
u8_t ram_heap[MEM_SIZE_ALIGNED +
(2*SIZEOF_STRUCT_MEM) + MEM_ALIGNMENT];
#define LWIP_RAM_HEAP_POINTER ram_heap
static u8_t *ram;
static struct mem *ram_end;
static struct mem *lfree;
2)、内存堆初始化mem_init
void mem_init(void)
{
struct mem *mem;
/* align the heap */
// LWIP_RAM_HEAP_POINTER <=> ram_heap
ram = (u8_t *)LWIP_MEM_ALIGN(LWIP_RAM_HEAP_POINTER);
/* initialize the start of the heap */
mem = (struct mem *)(void *)ram;
mem->next = MEM_SIZE_ALIGNED;
mem->prev = 0;
mem->used = 0;
/* initialize the end of the heap */
ram_end = (struct mem *)(void *)&ram[MEM_SIZE_ALIGNED];
ram_end->used = 1;
ram_end->next = MEM_SIZE_ALIGNED;
ram_end->prev = MEM_SIZE_ALIGNED;
//initialize the lowest-free pointer to the start of the heap
lfree = (struct mem *)(void *)ram;
MEM_STATS_AVAIL(avail, MEM_SIZE_ALIGNED);
if(sys_mutex_new(&mem_mutex) != ERR_OK) {
LWIP_ASSERT("failed to create mem_mutex", 0);
}
}
初始化及分配2个内存块的结构示意图如:

3)、内存堆分配mem_malloc
void *mem_malloc(mem_size_t size)
{
mem_size_t ptr, ptr2;
struct mem *mem, *mem2;
LWIP_MEM_ALLOC_DECL_PROTECT();
if (size == 0) {
return NULL;
}
/* Expand the size of the allocated memory region so that we can adjust for alignment. */
size = LWIP_MEM_ALIGN_SIZE(size);
//检查申请空间的大小
if(size < MIN_SIZE_ALIGNED) {
size = MIN_SIZE_ALIGNED;
}
if (size > MEM_SIZE_ALIGNED) {
return NULL;
}
sys_mutex_lock(&mem_mutex);
LWIP_MEM_ALLOC_PROTECT();
for (ptr = (mem_size_t)((u8_t *)lfree - ram);
ptr < MEM_SIZE_ALIGNED - size;
ptr = ((struct mem *)(void *)&ram[ptr])->next)
{
mem = (struct mem *)(void *)&ram[ptr];
// 判断该空闲内存块未用且容量是否大于size
if ((!mem->used) &&
(mem->next - (ptr + SIZEOF_STRUCT_MEM)) >= size) {
//判断该空闲块容量是否大于size + MIN_SIZE_ALIGNED
if (mem->next - (ptr + SIZEOF_STRUCT_MEM) >= (size + SIZEOF_STRUCT_MEM + MIN_SIZE_ALIGNED)) {
//申请size大小内存块后,组织剩下的空闲内存
ptr2 = ptr + SIZEOF_STRUCT_MEM + size;
/* create mem2 struct */
mem2 = (struct mem *)(void *)&ram[ptr2];
mem2->used = 0;
mem2->next = mem->next;
mem2->prev = ptr;
// and insert it between mem and mem->next
mem->next = ptr2;
mem->used = 1;
if (mem2->next != MEM_SIZE_ALIGNED) {
((struct mem *)(void *)&ram[mem2->next])->prev = ptr2;
}
MEM_STATS_INC_USED(used, (size + SIZEOF_STRUCT_MEM));
} else {
//空闲块容量大于size,小于size + MIN_SIZE_ALIGNE时,直接占用该内存块
mem->used = 1;
MEM_STATS_INC_USED(used, mem->next -
(mem_size_t)((u8_t *)mem - ram));
}
//移动lfree指针
if (mem == lfree) {
struct mem *cur = lfree;
// Find next free block after mem and update lowest free pointer
while (cur->used && cur != ram_end) {
cur = (struct mem *)(void *)&ram[cur->next];
}
lfree = cur;
}
LWIP_MEM_ALLOC_UNPROTECT();
sys_mutex_unlock(&mem_mutex);
return (u8_t *)mem + SIZEOF_STRUCT_MEM;
}
}
MEM_STATS_INC(err);
LWIP_MEM_ALLOC_UNPROTECT();
sys_mutex_unlock(&mem_mutex);
return NULL;
}
多次分配内存堆后的结构示意图

4)、内存堆释放mem_free
void mem_free(void *rmem)
{
struct mem *mem;
LWIP_MEM_FREE_DECL_PROTECT();
if (rmem == NULL) {
return;
}
if ((u8_t *)rmem < (u8_t *)ram || (u8_t *)rmem >= (u8_t *)ram_end) {
SYS_ARCH_DECL_PROTECT(lev);
/* protect mem stats from concurrent access */
SYS_ARCH_PROTECT(lev);
MEM_STATS_INC(illegal);
SYS_ARCH_UNPROTECT(lev);
return;
}
/* protect the heap from concurrent access */
/* Get the corresponding struct mem ... */
mem = (struct mem *)(void *)((u8_t *)rmem -
SIZEOF_STRUCT_MEM);
mem->used = 0;
if (mem < lfree) {
/* the newly freed struct is now the lowest */
lfree = mem;
}
MEM_STATS_DEC_USED(used, mem->next - (mem_size_t)(((u8_t *)mem - ram)));
//finally, see if prev or next are free also
// 合并相邻空闲块
plug_holes(mem);
LWIP_MEM_FREE_UNPROTECT();
}
合并相邻空闲块函数plug_holes
static void plug_holes(struct mem *mem)
{
struct mem *nmem;
struct mem *pmem;
//检测释放内存块指向的下一个内存块
nmem = (struct mem *)(void *)&ram[mem->next];
if (mem != nmem && nmem->used == 0 &&
(u8_t *)nmem != (u8_t *)ram_end) {
if (lfree == nmem) {
lfree = mem;
}
mem->next = nmem->next;
((struct mem *)(void *)&ram[nmem->next])->prev = (mem_size_t)((u8_t *)mem - ram);
}
//检测释放内存块指向的上一个内存块
pmem = (struct mem *)(void *)&ram[mem->prev];
if (pmem != mem && pmem->used == 0) {
if (lfree == mem) {
lfree = pmem;
}
pmem->next = mem->next;
((struct mem *)(void *)&ram[mem->next])->prev = (mem_size_t)((u8_t *)pmem - ram);
}
}
|