lwip之内存管理

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

初始化内存池结构示意图
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 > 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个内存块的结构示意图如:
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);
  }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值