LwIP protocol stack source code analysis (reading notes)--memory management--dynamic memory pool POOL allocation strategy source code

This chapter analyzes the first allocation strategy of dynamic memory heap (HEAP), following the previous article
LwIP protocol stack source code analysis (reading notes) – memory management – ​​mechanism strategy analysis
LwIP protocol stack source code analysis (reading notes) – memory management – ​​dynamic memory Heap (HEAP) allocation strategy source code

Organizational structure:

write picture description here

Source code analysis:

See the wlip memp.c file.
Necessary structure explanation:
memory pool size = single memory type 1 size number 1 + single memory type 2 size number 2 +... + single memory type MEMP_MAX * number MEMP_MAX, number of
memory pool elements = number 1 + number MEMP_MAX;

/** This array holds the first free element of each pool.
 *  Elements form a linked list.==该数组保存一张链表,节点数=MEMP_MAX种类型的内存类型*对应的数目,即内存池元素个数 */
static struct memp *memp_tab[MEMP_MAX];
/** This array holds the number of elements in each pool. ==该数组包含了每种内存类型的数目*/
static const u16_t memp_num[MEMP_MAX] = {
#define LWIP_MEMPOOL(name,num,size,desc)  (num),
#include "lwip/memp_std.h"
};
/** This array holds the element sizes of each pool. ==该数组包含了每种内存类型结构的单个大小(不与数目相乘)*/
#if !MEM_USE_POOLS && !MEMP_MEM_MALLOC
static
#endif
const u16_t memp_sizes[MEMP_MAX] = {
#define LWIP_MEMPOOL(name,num,size,desc)  LWIP_MEM_ALIGN_SIZE(size),
#include "lwip/memp_std.h"
};

memp_init) :



/**
 * Initialize this module.
 * 
 * Carves out memp_memory into linked lists for each pool-type.
 */
void
memp_init(void)
{
  struct memp *memp;
  u16_t i, j;

  for (i = 0; i < MEMP_MAX; ++i) {
    MEMP_STATS_AVAIL(used, i, 0);
    MEMP_STATS_AVAIL(max, i, 0);
    MEMP_STATS_AVAIL(err, i, 0);
    MEMP_STATS_AVAIL(avail, i, memp_num[i]);
  }

#if !MEMP_SEPARATE_POOLS
  memp = (struct memp *)LWIP_MEM_ALIGN(memp_memory);//内存地址对齐
#endif /* !MEMP_SEPARATE_POOLS */
  /* for every pool: */
  for (i = 0; i < MEMP_MAX; ++i) {//创建链表:节点数=MEMP_MAX种类型的内存类型*对应的数目 
    memp_tab[i] = NULL;
#if MEMP_SEPARATE_POOLS
    memp = (struct memp*)memp_bases[i];
#endif /* MEMP_SEPARATE_POOLS */
    /* create a linked list of memp elements==创建memp链表==将memp_num[i]个相同内存类型之间 建立链表连接,由后向前 */
    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]//更新memp为下一个块地址
#if MEMP_OVERFLOW_CHECK
        + MEMP_SANITY_REGION_AFTER_ALIGNED
#endif
      );
    }
  }
#if MEMP_OVERFLOW_CHECK
  memp_overflow_init();
  /* check everything a first time to see if it worked */
  memp_overflow_check_all();
#endif /* MEMP_OVERFLOW_CHECK */
}

memp_malloc) :


/**
 * Get an element from a specific pool.
 *
 * @param type the pool to get an element from
 *
 * the debug version has two more parameters:
 * @param file file name calling this function
 * @param line number of line where this function is called
 *
 * @return a pointer to the allocated memory or a NULL pointer on error
 */
void *
#if !MEMP_OVERFLOW_CHECK
memp_malloc(memp_t type)
#else
memp_malloc_fn(memp_t type, const char* file, const int line)
#endif
{
  struct memp *memp;
  SYS_ARCH_DECL_PROTECT(old_level);

  LWIP_ERROR("memp_malloc: type < MEMP_MAX", (type < MEMP_MAX), return NULL;);

  SYS_ARCH_PROTECT(old_level);
#if MEMP_OVERFLOW_CHECK >= 2
  memp_overflow_check_all();
#endif /* MEMP_OVERFLOW_CHECK >= 2 */

  memp = memp_tab[type];//获取内存类型的首地址

  if (memp != NULL) {
    memp_tab[type] = memp->next;//更新memp_tab
#if MEMP_OVERFLOW_CHECK
    memp->next = NULL;
    memp->file = file;
    memp->line = line;
#endif /* MEMP_OVERFLOW_CHECK */
    MEMP_STATS_INC_USED(used, type);
    LWIP_ASSERT("memp_malloc: memp properly aligned",
                ((mem_ptr_t)memp % MEM_ALIGNMENT) == 0);
    memp = (struct memp*)(void *)((u8_t*)memp + MEMP_SIZE);//类型强转
  } else {
    LWIP_DEBUGF(MEMP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("memp_malloc: out of memory in pool %s\n", memp_desc[type]));
    MEMP_STATS_INC(err, type);
  }

  SYS_ARCH_UNPROTECT(old_level);

  return memp;
}

memp_free :


/**
 * Put an element back into its pool.
 *
 * @param type the pool where to put mem
 * @param mem the memp element to free
 */
void
memp_free(memp_t type, void *mem)
{
  struct memp *memp;
  SYS_ARCH_DECL_PROTECT(old_level);

  if (mem == NULL) {
    return;
  }
  LWIP_ASSERT("memp_free: mem properly aligned",
                ((mem_ptr_t)mem % MEM_ALIGNMENT) == 0);

  memp = (struct memp *)(void *)((u8_t*)mem - MEMP_SIZE);

  SYS_ARCH_PROTECT(old_level);

#if MEMP_OVERFLOW_CHECK
#if MEMP_OVERFLOW_CHECK >= 2
  memp_overflow_check_all();
#else
  memp_overflow_check_element_overflow(memp, type);
  memp_overflow_check_element_underflow(memp, type);
#endif /* MEMP_OVERFLOW_CHECK >= 2 */
#endif /* MEMP_OVERFLOW_CHECK */

  MEMP_STATS_DEC(used, type); 

  memp->next = memp_tab[type]; //插入链表
  memp_tab[type] = memp;

#if MEMP_SANITY_CHECK
  LWIP_ASSERT("memp sanity", memp_sanity());
#endif /* MEMP_SANITY_CHECK */

  SYS_ARCH_UNPROTECT(old_level);

}

ask:

The lwip memory pool is organized as a linked list, but where is the memory of the linked list itself? Looking at the code implementation, he is in the pool. If so, isn't the data completely messed up?

No mess, the first 4 bytes of each pool are used as pointers; after the memory is allocated, these four bytes can be used to store data. At this time, the allocated block is no longer on the linked list, so the pointer will not be retained, and there is no need to retain it.

Some people say that the lwip memory pool will waste memory, but the pool implemented by lwip has been well planned. Logically speaking, if it is used reasonably, will it be wasted?

The concept of waste here is that, for example, the system reserves five, but in reality you will only use three. There are two reserved spaces that will never be used.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325401001&siteId=291194637