阅读mheap代码原因主要是在vpp使用中遇到了一个bug,主要对mheap底层结构不太了解,用将近一周的时间定位了此问题(mhash代码存在bug)。问题原因在vpp-1844单子里面也比较详细。
1、系统malloc和mmap对比
malloc使用brk分配的内存,需要等到高地址内存释放以后才能释放,存在内存“空洞”,申请大内存(大于128k)时候使用的是mmap系统调用;
mmap系统调用是在堆和栈之间分配一块内存,这块内存可以单独释放,不会造成内存“空洞”,也不会影响到堆顶内存的缩减释放。
mmap的缺点是按需调页:一页大小4k bytes,如果需要的内存很小,会造成内存浪费;频繁的mmap、munmap会造成大量的缺页中断,给CPU带来额外的负担。
所以小内存或频繁的申请释放用malloc;一次申请终身使用的内存用mmap。

2、vpp mheap使用
在 C 语言的动态申请内存技术中,相比起 malloc/free 系统调用,内存池(memory pool)是预先在系统中请求一大片连续的内存空间,然后在运行时根据实际需要分配出去的技术。使用内存池的优点有:
(1)速度远比 malloc/free 快,因为减少了系统调用的次数,特别是频繁申请/释放内存块的情况
(2)避免了频繁申请/释放内存之后,造成系统的大量内存碎片
3、Mheap内存分布结构

4、mheap_elt_t结构内存分布

mheap_prev_elt 我认为代码书写时错误的。。
/*宏表示union部分user_data的长度,所以在mheap_prev_elt 函数直接使用是存在问题的。*/
#define MHEAP_ELT_OVERHEAD_BYTES (sizeof (mheap_elt_t) - STRUCT_OFFSET_OF (mheap_elt_t, user_data))当前使用没有问题主要是user_data正好将mheap_elt_t结构一分为二。索引代码功能是正确的。
always_inline mheap_elt_t *
mheap_prev_elt (mheap_elt_t * e)
{
ASSERT (e->prev_n_user_data < MHEAP_N_USER_DATA_INVALID);
return ((void *) e
- e->prev_n_user_data * sizeof (e->user_data[0])
/*我认为这里只需要偏移 STRUCT_OFFSET_OF (mheap_elt_t, user_data) 长度*/
- MHEAP_ELT_OVERHEAD_BYTES);
}free_bin区内存结构
图片来源于呆呆辉文章

相关结构体注释

















