lwip之内存管理

来源:互联网 发布:手机淘宝的微淘在哪里 编辑:程序博客网 时间:2024/05/23 16:43

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==1MEMP_USE_CUSTOM_POOLS==1MEM_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

初始化内存池结构示意图
memp memory

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 > 64000Ltypedef u32_t mem_size_t;#define MEM_SIZE_F U32_F#elsetypedef 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_heapstatic 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个内存块的结构示意图如:
mem

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;}

多次分配内存堆后的结构示意图
ram

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);  }}
0 0
原创粉丝点击