lwip内存池

lwip memp(内存池)

内存池声明过程

内存池声明宏定义


#define LWIP_MEMPOOL(name,num,size,desc) LWIP_MEMPOOL_DECLARE(name,num,size,desc)

在 #include "lwip/memp.h" 文件中进行定义
/**
 * @ingroup mempool
 * Declare a private memory pool
 * Private mempools example:
 * .h: only when pool is used in multiple .c files: LWIP_MEMPOOL_PROTOTYPE(my_private_pool);
 * .c:
 *   - in global variables section: LWIP_MEMPOOL_DECLARE(my_private_pool, 10, sizeof(foo), "Some description")
 *   - call ONCE before using pool (e.g. in some init() function): LWIP_MEMPOOL_INIT(my_private_pool);
 *   - allocate: void* my_new_mem = LWIP_MEMPOOL_ALLOC(my_private_pool);
 *   - free: LWIP_MEMPOOL_FREE(my_private_pool, my_new_mem);
 *
 * To relocate a pool, declare it as extern in cc.h. Example for GCC:
 *   extern u8_t \_\_attribute\_\_((section(".onchip_mem"))) memp_memory_my_private_pool_base[];
 */
#define LWIP_MEMPOOL_DECLARE(name,num,size,desc) \
  //声明内存空间	
  LWIP_DECLARE_MEMORY_ALIGNED(memp_memory_ ## name ## _base, ((num) * (MEMP_SIZE + MEMP_ALIGN_SIZE(size)))); \
    \
  //声明内存统计数据实例	
  //#define LWIP_MEMPOOL_DECLARE_STATS_INSTANCE(name) static struct stats_mem name;
  LWIP_MEMPOOL_DECLARE_STATS_INSTANCE(memp_stats_ ## name) \
    \
  //声明内存池表
  static struct memp *memp_tab_ ## name; \
    \
  //声明内存池描述结构体
  //一类内存池对应一种描述结构体
  const struct memp_desc memp_ ## name = { \
    DECLARE_LWIP_MEMPOOL_DESC(desc) \
    LWIP_MEMPOOL_DECLARE_STATS_REFERENCE(memp_stats_ ## name) \
    LWIP_MEM_ALIGN_SIZE(size), \
    (num), \
    memp_memory_ ## name ## _base, \
    &memp_tab_ ## name \
  };

声明内存统计数据实例

/** Memory stats */
struct stats_mem {
#if defined(LWIP_DEBUG) || LWIP_STATS_DISPLAY
  const char *name;
#endif /* defined(LWIP_DEBUG) || LWIP_STATS_DISPLAY */
  STAT_COUNTER err;
  mem_size_t avail;				//有效元素数量
  mem_size_t used;				//已用元素数量
  mem_size_t max;				//最大元素数量
  STAT_COUNTER illegal;
};

内存池结构体

struct memp {
  struct memp *next;
#if MEMP_OVERFLOW_CHECK
  const char *file;
  int line;
#endif /* MEMP_OVERFLOW_CHECK */
};

内存池描述结构体

/** Memory pool descriptor */
struct memp_desc {
#if defined(LWIP_DEBUG) || MEMP_OVERFLOW_CHECK || LWIP_STATS_DISPLAY
  /** Textual description */
  const char *desc;				//内存池描述字符
#endif /* LWIP_DEBUG || MEMP_OVERFLOW_CHECK || LWIP_STATS_DISPLAY */
#if MEMP_STATS
  /** Statistics */
  struct stats_mem *stats;		//内存状态统计
#endif

  /** Element size */
  u16_t size;					//元素大小

#if !MEMP_MEM_MALLOC
  /** Number of elements */
  u16_t num;					//元素数量

  /** Base address */
  u8_t *base;					//内存池基地址

  /** First free element of each pool. Elements form a linked list. */
  struct memp **tab;			//空闲元素首指针
#endif /* MEMP_MEM_MALLOC */
};

内存池声明示例:
所有使用到的内存池在#include "lwip/priv/memp_std.h"文件中进行声明,实际使用了全局变量作为内存池的空间。

LWIP_MEMPOOL(TCP_SEG, MEMP_NUM_TCP_SEG, sizeof(struct tcp_seg), "TCP_SEG")为例说明内存池分配
的过程。

LWIP_MEMPOOL_DECLARE宏的展开为

LWIP_MEMPOOL_DECLARE(name,num,size,desc)

LWIP_MEMPOOL_DECLARE(TCP_SEG, MEMP_NUM_TCP_SEG, sizeof(struct tcp_seg), "TCP_SEG") \
	//声明内存空间
	LWIP_DECLARE_MEMORY_ALIGNED(memp_memory_TCP_SEG_base, ((MEMP_NUM_TCP_SEG) * (MEMP_SIZE + MEMP_ALIGN_SIZE(sizeof(struct tcp_seg))))); \
    \
    //声明内存统计数据实例
	LWIP_MEMPOOL_DECLARE_STATS_INSTANCE(memp_stats_TCP_SEG) \
    \
	//声明内存池表
    static struct memp *memp_tab_TCP_SEG; \	
	\
    //声明内存池描述结构体
    //一类内存池对应一种描述结构体
    const struct memp_desc memp_TCP_SEG = { \
    DECLARE_LWIP_MEMPOOL_DESC("TCP_SEG") \
    LWIP_MEMPOOL_DECLARE_STATS_REFERENCE(memp_stats_TCP_SEG) \
    LWIP_MEM_ALIGN_SIZE(sizeof(struct tcp_seg)), \
    (MEMP_NUM_TCP_SEG), \
    memp_memory_TCP_SEG_base, \
    &memp_tab_TCP_SEG \
  };

以上使用宏定义,定义对应的内存池内存空间。

LWIP_DECLARE_MEMORY_ALIGNED宏用于定义内存空间,其定义如下:

/** Allocates a memory buffer of specified size that is of sufficient size to align
 * its start address using LWIP_MEM_ALIGN.
 * You can declare your own version here e.g. to enforce alignment without adding
 * trailing padding bytes (see LWIP_MEM_ALIGN_BUFFER) or your own section placement
 * requirements.\n
 * e.g. if you use gcc and need 32 bit alignment:\n
 * \#define LWIP_DECLARE_MEMORY_ALIGNED(variable_name, size) u8_t variable_name[size] \_\_attribute\_\_((aligned(4)))\n
 * or more portable:\n
 * \#define LWIP_DECLARE_MEMORY_ALIGNED(variable_name, size) u32_t variable_name[(size + sizeof(u32_t) - 1) / sizeof(u32_t)]
 */
#ifndef LWIP_DECLARE_MEMORY_ALIGNED
#define LWIP_DECLARE_MEMORY_ALIGNED(variable_name, size) u8_t variable_name[LWIP_MEM_ALIGN_BUFFER(size)]
#endif

使用memp_memory_TCP_SEG_base作为数组的名称,数组大小为((MEMP_NUM_TCP_SEG) * (MEMP_SIZE + MEMP_ALIGN_SIZE(sizeof(struct tcp_seg))))字节。

定义的内存空间,可以在编译生成的.map文件中查到:

memp_memory_TCP_SEG_base                 0x6800b550   Data       20003  memp.o(.bss)

LWIP_MEMPOOL_DECLARE_STATS_INSTANCE宏用于声明内存池统计结构体。

memp.c文件的开头部分,有如下两个宏定义的地方

#define LWIP_MEMPOOL(name,num,size,desc) LWIP_MEMPOOL_DECLARE(name,num,size,desc)
#include "lwip/priv/memp_std.h"

const struct memp_desc *const memp_pools[MEMP_MAX] = {
#define LWIP_MEMPOOL(name,num,size,desc) &memp_ ## name,
#include "lwip/priv/memp_std.h"
};

通过两次定义宏LWIP_MEMPOOL,巧妙地构建所有的内存池空间。

第一次定义LWIP_MEMPOOL宏为LWIP_MEMPOOL_DECLARE,然后再把lwip/priv/memp_std.h文件的内存包括进行。
会进入lwip/priv/memp_std.h文件,对每个宏定义LWIP_MEMPOOL(TCP_SEG, MEMP_NUM_TCP_SEG, sizeof(struct tcp_seg), "TCP_SEG")
对每个宏定义用LWIP_MEMPOOL_DECLARE进行展开,分包声明结构体和内存空间。

第二次定义LWIP_MEMPOOL宏为&memp_ ## name,在memp_pools指针数组中。
LWIP_MEMPOOL宏定义下面,包含了"lwip/priv/memp_std.h"文件。
因此会再次进入该文件,使用新的&memp_ ## name宏对文件下的每个项进行定义。

第一次调用LWIP_MEMPOOL宏时,创建以const struct memp_desc memp_ ## name命令的结构体,
第二次调用LWIP_MEMPOOL宏时,对该结构体进行引用。

使用memp_pools数组,对所有的内存池进行统一管理。

内存池使用

内存池使用之前,首先调用memp_init()memp_pools数组进行初始化处理。

调用memp_init_pool(const struct memp_desc *desc)函数,对具体内初池进行初始化。
主要是对齐内存池首地址、清空内存池空间、构建内存池链表、初始化内存统计结构体。

使用分配时,调用memp_malloc(memp_t type)函数,传入需要分配的内存池类型。
调用do_memp_malloc_pool(const struct memp_desc *desc)进行实际内存分配。

使用过后,调用memp_free(memp_t type, void *mem)进行内存释放。

发布了17 篇原创文章 · 获赞 11 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/u010561799/article/details/105266379
今日推荐