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)進行內存釋放。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章