前几天在阅读源码中tcp session模块的时候,发现一个valloc相关的内存分配器。暂时还未了解具体的应用场景,今天就来简单剖析一下源码吧。
相关结构体描述
主要有2个结构体:
clib_
注意: 通过上述几个api接口,只运行添加内存chunk,不能对内存chunk进行删除。所以需要使用者合理的添加内存。
_main_t :内存分配管理结构体;
clib_valloc_chunk_t:内存块结构;
具体介绍如下:
接口api
1、向虚拟分配管理区添加一块内存区
代码语言:javascript复制void clib_valloc_add_chunk (clib_valloc_main_t * vam,
clib_valloc_chunk_t * template)
参数说明: 1、clib_valloc_main_t * vam :指向内存分配器管理结构指针。 2、clib_valloc_chunk_t * template :指向内存块chunk的指针,该chunk块描述要添加的虚拟地址的基地址及大小。 功能描述: 1、首先进行加锁,读取管理结构的头节点索引,如果索引为全ff,直接从pool池获取内存chunk,并设置hash,解锁返回。 2、如果不全ff,获取头节点内存chunk。如果添加基地址是否大于链表头节点的基地址。将当前设置为头节点,设置hash<基地址,pool索引>,并更新管理结构头节点索引。否则添加到双向链表尾部。
疑问? 1、添加内存chunk时,为什么需要判断基地址的大小?而且加到头节点?
2、内存分配器管理结构初始化
代码语言:javascript复制void clib_valloc_init (clib_valloc_main_t * vam, clib_valloc_chunk_t * template,int need_lock)
参数说明: 1、clib_valloc_main_t * vam :指向内存分配器管理结构指针。 2、clib_valloc_chunk_t * template :指向内存块chunk的指针,该chunk块描述要添加的虚拟地址的基地址及大小。 3、int need_lock:是否需要加锁,多线程模式。 功能描述: 1、对管理结构进行初始化操作,成员进行赋值。 2、调用clib_valloc_add_chunk接口添加内存块。
3、从内存管理结构中申请内存。
代码语言:javascript复制uword
clib_valloc_alloc (clib_valloc_main_t * vam, uword size,
int os_out_of_memory_on_failure)
参数说明: 1、clib_valloc_main_t * vam :指向内存分配器管理结构指针。 2、uword size:申请空间的大小。 3、os_out_of_memory_on_failure:内存不足时,是否需要产生异常。 功能描述: 1、尝试进行加锁,获取管理结构头节点索引。 2、遍历双向链表,找到空闲状态内存chunk且满足申请大小。如果内存chunk大小大于申请大小,对内存chunk分割,分割后的chunk添加到当前节点后面。解锁后返回内存首地址。
注意,双向链表的节点顺序不能随意变更。否则free后无法进行合并。
4 内存释放到内存管理结构
代码语言:javascript复制uword
clib_valloc_free (clib_valloc_main_t * vam, uword baseva)
参数说明: 1、clib_valloc_main_t * vam :指向内存分配器管理结构指针。 2、uword baseva:内存地址。 功能说明: 1、通过baseva地址,hash得到pool索引,找到内存chunk。 2、判断当前内存chunk前后地址连续且处于空闲状态进行合并处理。
注意: 通过上述几个api接口,只运行添加内存chunk,不能对内存chunk进行删除。所以需要使用者合理的添加内存。
总结
本文只简单描述了内存管理的结构及相关接口api,对这种内存分配器的使用场景还不熟悉,待后续补充。