🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
内存池的初始化之后,这些内存池中的内存块就可以使用了,这就需要用户通过memp_malloc函数进行申请内存块,而内存块的大小就是指定的大小,其过程很简单,就是根据内存池的类型去选择从哪个内存池进行分配,因为不同类型的内存池中内存块大小是不一样的,比如TCP_PCB与UDP_PCB的大小就不一样,所以申请内存的时候传入的参数是内存池的类型而并非要申请的内存大小,系统中所有的内存池类型都会被记录在memp_pools数组中,我们可以将该数组称之为内存池描述表,它负责将系统所有的内存池信息描述并且记录下来,这样子在申请内存的时候就能很迅速得到一个对应的内存块,内存分配函数的源码具体见代码清单 5 7。 ``` 1 void * 2 memp_malloc(memp_t type) 3 { 4 void *memp; 5 LWIP_ERROR("memp_malloc: type < MEMP_MAX", (type < MEMP_MAX), return NULL;); 6 7 memp = do_memp_malloc_pool(memp_pools[type]); 8 9 return memp; 10 } 11 12 static void * 13 do_memp_malloc_pool(const struct memp_desc *desc) 14 { 15 struct memp *memp; 16 SYS_ARCH_DECL_PROTECT(old_level); 17 memp = *desc->tab; 18 if (memp != NULL) 19 { 20 21 *desc->tab = memp->next; 22 23 LWIP_ASSERT("memp_malloc: memp properly aligned", 24 ((mem_ptr_t)memp % MEM_ALIGNMENT) == 0); 25 26 SYS_ARCH_UNPROTECT(old_level); 27 /* cast through u8_t* to get rid of alignment warnings */ 28 return ((u8_t *)memp + MEMP_SIZE); 29 } 30 else 31 { 32 SYS_ARCH_UNPROTECT(old_level); 33 LWIP_DEBUGF(MEMP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, 34 ("memp_malloc: out of memory in pool %s\n", desc->desc)); 35 } 36 return NULL; 37 } ``` 内存池申请函数的核心代码就一句,那就是memp = *desc->tab;,通过这句代码,能直接得到对应内存块中的第一个空闲内存块,如果该内存块不是NULL,则将其取出,并且移动 *desc->tab指针,指向下一个空闲内存块,然后将((u8_t *)memp + MEMP_SIZE)返回,MEMP_SIZE偏移的空间大小,因为内存块需要一些空间存储内存块相关的信息,该宏定义的值是(LWIP_MEM_ALIGN_SIZE(sizeof(struct memp)) + MEM_SANITY_REGION_BEFORE_ALIGNED),我们暂时无需理会它,只要知道申请内存块后返回的地址是直接可用的地址即可,而偏移的MEMP_SIZE这部分内容是内存分配器管理的空间,用户是不允许触碰的地方,否则就很可能发生错误。