阅读mheap代码原因主要是在vpp使用中遇到了一个bug,主要对mheap底层结构不太了解,用将近一周的时间定位了此问题(mhash代码存在bug)。问题原因在vpp-1844单子里面也比较详细。 

1、系统malloc和mmap对比

malloc使用brk分配的内存,需要等到高地址内存释放以后才能释放,存在内存“空洞”,申请大内存(大于128k)时候使用的是mmap系统调用;

mmap系统调用是在堆和栈之间分配一块内存,这块内存可以单独释放,不会造成内存“空洞”,也不会影响到堆顶内存的缩减释放。

mmap的缺点是按需调页:一页大小4k bytes,如果需要的内存很小,会造成内存浪费;频繁的mmap、munmap会造成大量的缺页中断,给CPU带来额外的负担。

所以小内存或频繁的申请释放用malloc;一次申请终身使用的内存用mmap。

mpp架构对比 mpp架构缺点_内存释放



2、vpp mheap使用

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

3、Mheap内存分布结构

mpp架构对比 mpp架构缺点_mpp架构对比_02

4、mheap_elt_t结构内存分布

mpp架构对比 mpp架构缺点_系统调用_03


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区内存结构

图片来源于呆呆辉文章

mpp架构对比 mpp架构缺点_mpp架构对比_04

相关结构体注释

mpp架构对比 mpp架构缺点_系统调用_05