LwIP之动态内存池

从动态内存池的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
}

LwIP之动态内存池_第1张图片

 

申请内存池单元

/* 申请一个内存池单元 */
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
}

 

 

你可能感兴趣的:(LwIP)