zl程序教程

您现在的位置是:首页 >  工具

当前栏目

vppinfra ---heap学习

学习 --- Heap vppinfra
2023-06-13 09:15:37 时间

上一节我们介绍hash的使用,本来这节打算介绍mhash,但是mhash结构中使用了另外一种结构heap:可变长度的内存池管理结构。下面是vpp官方对heap的说明:

Rarely used (pool are faster) 
很少使用,pool内存池更快
still efficient 
但是也很有用
to be used if you need variably sized allocations 
如果需要可变大小的分配,则使用

heap结构比pool结构处理比较复杂,我们可以先从heap的测试用例来了解heap的使用方法,再深入了解其内部处理逻辑。

  • heap对外使用方法:

从vppinfra/test_heap.c文件里面截取一部分代码来大概介绍一下具体的使用。heap和pool一样,有两种使用方式:

1:固定内存大小,静态heap--超过大小可能会报异常,这个应该和pool一样的,需要注意。

2: 动态申请内存大小,动态heap--这个对使用者没有限制。

我们主要介绍动态申请heap内存方式:

/* 动态heap内存使用函数。我们可以参考单元测试用例。
 * u32 *v;heap管理堆数据区域头指针
 *  u32 handle:管理内存块结构体的下标:如:heap_elt_t *p =H->elts[handle]。
 *  u32 size :要申请数据的占用多少sizeof ((v)[0]),因为底层是vec操作函数。
 *            这个可能比传入size要大,可能会进行 align字节对齐。    
 *  u32 align:内存对齐的大小
*/
u32 offset = heap_alloc_aligned(v,size,align,handle);
/*我们申请内存的首地址head 可以通过下面方式直接得到*/
u32 * head = v + offset;
/*headle 我们必须要保存的,通过headle 我们可以用来释放这块内存*/
 heap_dealloc (v, handle);
 /*heap_elt_with_handle(v,handle)*/
 heap_elt_with_handle(v,handle);
  • heap 管理结构及其内存分布:
/* Header for heaps. */
typedef struct
{
  /* Vector of used and free elements. heap管理数据块*/
  heap_elt_t *elts;
  /* For elt_bytes < sizeof (u32) we need some extra space
     per elt to store free list index. */
  u32 *small_free_elt_free_index;
  /* Vector of free indices of elts array. */
  u32 *free_elts;
  /* Indices of free elts indexed by size bin. */
  u32 **free_lists;
  format_function_t *format_elt;
  /* Used for validation/debugging. */
    uword *used_elt_bitmap;
  /* First and last element of doubly linked chain of elements. */
  u32 head, tail;
  /*used_count : 已经使用的个数,max_len 静态heap使用的,最大大小*/
  u32 used_count, max_len;
  /* Number of bytes in a help element. 
   *这个比较关键,heap堆的数据类型的字节数 ,等于size(v[0])*/
  u32 elt_bytes;
  u32 flags;
  /* Static heaps are made from external memory given to
     us by user and are not re-sizable vectors. */
#define HEAP_IS_STATIC (1)
} heap_header_t;

heap堆内存的块管理结构:

主要是offset :bit31 位:表示当前内存块是free还是busy状态。

bit0~30:表示举例heap 堆头指针V的偏移量大小。

next 和prev : 当前管理内存块的前后内存块是连续的,这样在heap_dealloc释放内存块时,我们可以判断前后是否free的,如果是free的,我们需要合并成大的内存块。

heap_header 结构中elts和free_elts 说明:

elts 是vector结构,主要是保存heap堆管理结构,heap_alloc的参数handle表示当前申请的内存块的管理结构在elts的下标。

free_elts :比较好理解,就是存放已经不使用的heap_elt_t 数据块。

heap内存分布及内存块free区管理

这里有个疑问small_free_elt_free_index 结构的作用是什么?

在源码注释的地方有说明,当elt_bytes < 4字节时使用。存储

small_free_elt_free_index【handle index】= free_list_index的。

这个主要是在合并free elts时候使用。v【0】的大小因为不满足4字节,无法存储free_list_index,所有我们使用small_free_elt_free_index[handle]来找到在free_list[bin]的下标,从未可以从free_list中删除。

  • heap的简单api
  • 总结 简单介绍了一个heap的管理结构及底层处理方式,希望能帮助你很快熟悉heap的使用方式。heap管理还是比较麻烦的,因为涉及到频繁的内存合并和分割,相对于pool是非常不高效的。所以我们应该尽量不要使用它。