freeswitch APR库内存池

概述
的核心源代码是基于apr库开发的,在不同的系统上有很好的移植性 。
apr库中的大部分API都需要依赖于内存池,使用内存池简化内存管理,提高内存分配效率,减少内存操作中出错的概率 。
在fs的自定义模块开发中,我们也会用到内存池来操作内存,所以要对内存池的基本操作和使用限制有一定了解,防止错误的使用,导致程序运行问题 。
下面我们对apr的内存池接口做一个介绍 。
环境
:7.0 (Final)或以上版本
:v1.8.7
GCC:4.8.5
内存池源码
apr库的内存池源代码文件在libs/apr目录下
libs\apr\include\apr_pools.hlibs\apr\memory\unix\apr_pools.c
【freeswitch APR库内存池】内存池结构体的定义在.c文件中
struct apr_pool_t {apr_pool_t*parent;apr_pool_t*child;apr_pool_t*sibling;apr_pool_t**ref;cleanup_t*cleanups;cleanup_t*free_cleanups;apr_allocator_t*allocator;struct process_chain *subprocesses;apr_abortfunc_tabort_fn;apr_hash_t*user_data;const char*tag;#if APR_HAS_THREADSapr_thread_mutex_t*user_mutex;#endif#if !APR_POOL_DEBUGapr_memnode_t*active;apr_memnode_t*self; /* The node containing the pool itself */char*self_first_avail;#else /* APR_POOL_DEBUG */apr_pool_t*joined; /* the caller has guaranteed that this pool* will survive as long as ->joined */debug_node_t*nodes;const char*file_line;apr_uint32_tcreation_flags;unsigned intstat_alloc;unsigned intstat_total_alloc;unsigned intstat_clear;#if APR_HAS_THREADSapr_os_thread_towner;apr_thread_mutex_t*mutex;#endif /* APR_HAS_THREADS */#endif /* APR_POOL_DEBUG */#ifdef NETWAREapr_os_proc_towner_proc;#endif /* defined(NETWARE) */};
从结构体的定义来看,在使用内存池的过程中主要关注“ *;”和“char *;”俩个变量 。
变量是当前内存池中内存节点链表的第一个节点,也可以从名字理解是活动节点 。
变量是当前内存池中可用内存的起始点 。
常用函数
查看源代码头文件libs\apr\\.h
…APR_DECLARE(apr_status_t) apr_pool_create(apr_pool_t **newpool, apr_pool_t *parent);APR_DECLARE(void) apr_pool_clear(apr_pool_t *p);APR_DECLARE(void) apr_pool_destroy(apr_pool_t *p);APR_DECLARE(void *) apr_palloc(apr_pool_t *p, apr_size_t size);…
使用函数创建内存池
使用函数清空内存池
使用函数销毁整个内存池
使用函数从内存池获取指定大小的内存块
创建
接口是的简化版,省略了4个参数中的后俩个,简化了用户的调用过程,下面我们介绍的代码逻辑 。
传入参数父节点为空,则使用作为父节点传入参数内存分配失败回调函数为空,则使用父节点的回调函数传入参数分配器为空,则使用父节点的分配器使用分配器获取一块内存节点node,大小为“ - ”初始化内存池pool,对“pool->”赋值为节点node
这里可以看出内存池pool刚创建的时候,“pool->”变量只有一个内存节点,大小为“ - ”,根据宏定义计算大小为8192-40=8152字节 。
清空clear
代码逻辑 。
销毁内存池pool的所有子内存池 。清理pool中的额外设置,包括、和 。重置pool->,保留1个内存节点并重置起点,释放多余节点 。
经过clear的内存池pool,回归到了刚刚出来的状态 。
销毁
的代码逻辑 。
销毁内存池pool的所有子内存池 。清理pool中的额外设置,包括、和父节点指针 。释放pool->所有节点 。销毁当前内存池拥有的分配器 。
经过的内存池,占用的所有内存都会释放掉 。
分配alloc
接口的代码逻辑 。
传入参数size按照8字节做内存对齐检查pool->节点数据,如果节点剩余空间满足分配请求的大小,则直接在pool->节点分配空间并返回 。获取pool->->next节点,检查节点数据 。如果节点剩余空间满足分配请求的大小,则将该节点从list中删除,保存为node节点 。如果节点剩余空间不满足,则使用pool->分配器获取大小为size的内存节点,保存为node节点 。修改node节点数据,记录node->并作为分配请求的返回数据,修改node->起始空间点+size 。将node节点插入列表的首位 。判断node节点的剩余空间,并将列表按照node节点剩余空间的大小由大到小排序。