freeswitch APR库内存池

概述
freeswitch的核心源代码是基于apr库开发的,在不同的系统上有很好的移植性。
apr库中的大部分API都需要依赖于内存池,使用内存池简化内存管理,提高内存分配效率,减少内存操作中出错的概率。
在fs的自定义模块开发中,我们也会用到内存池来操作内存,所以要对内存池的基本操作和使用限制有一定了解,防止错误的使用,导致程序运行问题。
下面我们对apr的内存池接口做一个介绍。
环境
centos:CentOS release 7.0 (Final)或以上版本
freeswitch:v1.8.7
GCC:4.8.5
内存池源码
apr库的内存池源代码文件在libs/apr目录下
libs\apr\include\apr_pools.h
libs\apr\memory\unix\apr_pools.c
内存池结构体apr_pool_t的定义在apr_pools.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_t abort_fn;
apr_hash_t *user_data;
const char *tag;
#if APR_HAS_THREADS
apr_thread_mutex_t *user_mutex;
#endif
#if !APR_POOL_DEBUG
apr_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_t creation_flags;
unsigned int stat_alloc;
unsigned int stat_total_alloc;
unsigned int stat_clear;
#if APR_HAS_THREADS
apr_os_thread_t owner;
apr_thread_mutex_t *mutex;
#endif /* APR_HAS_THREADS */
#endif /* APR_POOL_DEBUG */
#ifdef NETWARE
apr_os_proc_t owner_proc;
#endif /* defined(NETWARE) */
};
从结构体的定义来看,在使用内存池的过程中主要关注“apr_memnode_t *active;”和“char *self_first_avail;”俩个变量。
变量active是当前内存池中内存节点链表的第一个节点,也可以从名字理解是活动节点。
变量self_first_avail是当前内存池中可用内存的起始点。
常用函数
查看源代码头文件libs\apr\include\apr_pools.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);
…
使用apr_pool_create函数创建内存池
使用apr_pool_clear函数清空内存池
使用apr_pool_destroy函数销毁整个内存池
使用apr_palloc函数从内存池获取指定大小的内存块
创建create
apr_pool_create接口是apr_pool_create_ex的简化版,省略了4个参数中的后俩个,简化了用户的调用过程,下面我们介绍apr_pool_create_ex的代码逻辑。
- 传入参数parent父节点为空,则使用global_pool作为父节点
- 传入参数abort_fn内存分配失败回调函数为空,则使用父节点的回调函数
- 传入参数allocator分配器为空,则使用父节点的allocator分配器
- 使用allocator分配器获取一块内存节点node,大小为“MIN_ALLOC - APR_MEMNODE_T_SIZE”
- 初始化内存池pool,对“pool->active”赋值为节点node
这里可以看出内存池pool刚创建的时候,“pool->active”变量只有一个内存节点,大小为“MIN_ALLOC - APR_MEMNODE_T_SIZE”,根据宏定义计算大小为8192-40=8152字节。

清空clear
apr_pool_clear代码逻辑。
- 销毁内存池pool的所有子内存池。
- 清理pool中的额外设置,包括cleanup、subprocess和user_data。
- 重置pool->active,保留1个内存节点并重置起点,释放多余节点。
经过clear的内存池pool,回归到了刚刚create出来的状态。
销毁destory
apr_pool_destroy的代码逻辑。
- 销毁内存池pool的所有子内存池。
- 清理pool中的额外设置,包括cleanup、subprocess和父节点指针。
- 释放pool->active所有节点。
- 销毁当前内存池拥有的allocator分配器。
经过destory的内存池,占用的所有内存都会释放掉。
分配alloc
apr_palloc接口的代码逻辑。
- 传入参数size按照8字节做内存对齐
- 检查pool->active节点数据,如果节点剩余空间满足分配请求的大小,则直接在pool->active节点分配空间并返回。
- 获取pool->active->next节点,检查节点数据。
a) 如果节点剩余空间满足分配请求的大小,则将该节点从list中删除,保存为node节点。
b) 如果节点剩余空间不满足,则使用pool->allocator分配器获取大小为size的内存节点,保存为node节点。
- 修改node节点数据,记录node->first_avail并作为分配请求的返回数据,修改node->first_avail起始空间点+size。
- 将node节点插入active列表的首位。
- 判断node节点的剩余空间,并将active列表按照node节点剩余空间的大小由大到小排序 。
经过多次apr_palloc后,pool->active节点列表会产生多个新的节点,组成node链表。

自动扩展的问题
从分配alloc的代码逻辑可以看出,当内存池的空间不足时,apr_palloc会生成新的node节点扩展内存池空间。
内存池的内存空间并非是连续的,而是以单向链表的形式组合多个node节点,并且没有node个数的限制,理论上可以无限扩展直到内存被占满。
apr内存池没有内存回收接口,即使有内存空间明确不再需要使用,apr_pools也没有提供对应的回收接口,除非对整个内存池执行clear或者destroy,才能回收整个内存池空间。
总结
从apr库内存池的接口逻辑来看,该内存池更多适用于会话式场景,一个新的会话对应一个内存池,会话结束后,直接对内存池整体回收,简化会话过程中的内存管理。
而对于更长的生命周期的代码逻辑来说,使用上需要注意内存占用问题,防止内存的无限增长。
另外,apr内存池还有一些特性(包括调试、多线程、分配失败回调、子池等)需要更深入的学习和测试。
空空如常
求真得真
freeswitch APR库内存池的更多相关文章
- freeswitch APR库
概述 freeswitch依赖库源代码基本都可以在libs目录下找到. 在freeswitch的官方手册中,可以找到freeswitch的依赖库表格,其中freeswitch的core核心代码依赖库主 ...
- freeswitch APR库哈希表
概述 freeswitch的核心源代码是基于apr库开发的,在不同的系统上有很好的移植性. 哈希表在开发中应用的非常广泛,主要场景是对查询效率要求较高的逻辑,是典型的空间换时间的数据结构实现. 大多数 ...
- freeswitch APR-UTIL库线程池实现分析
概述 freeswitch的核心源代码是基于apr库开发的,在不同的系统上有很好的移植性. APR库在之前的文章中已经介绍过了,APR-UTIL库是和APR并列的工具库,它们都是由APACHE开源出来 ...
- freeswitch APR库线程读写锁
概述 freeswitch的核心源代码是基于apr库开发的,在不同的系统上有很好的移植性. 线程读写锁在多线程服务中有重要的作用.对于读数据比写数据频繁的服务,用读写锁代替互斥锁可以提高效率. 由于A ...
- Linux简易APR内存池学习笔记(带源码和实例)
先给个内存池的实现代码,里面带有个应用小例子和画的流程图,方便了解运行原理,代码 GCC 编译可用.可以自己上网下APR源码,参考代码下载链接: http://pan.baidu.com/s/1hq6 ...
- freeswitch APR-UTIL库消息队列实现
概述 freeswitch的核心源代码是基于apr库开发的,在不同的系统上有很好的移植性. APR库在之前的文章中已经介绍过了,APR-UTIL库是和APR并列的工具库,它们都是由APACHE开源出来 ...
- 不定长内存池之apr_pool
内存池可有效降低动态申请内存的次数,减少与内核态的交互,提升系统性能,减少内存碎片,增加内存空间使用率,避免内存泄漏的可能性,这么多的优点,没有理由不在系统中使用该技术. 内存池分类: 1. ...
- 基于C/S架构的3D对战网络游戏C++框架_05搭建系统开发环境与Boost智能指针、内存池初步了解
本系列博客主要是以对战游戏为背景介绍3D对战网络游戏常用的开发技术以及C++高级编程技巧,有了这些知识,就可以开发出中小型游戏项目或3D工业仿真项目. 笔者将分为以下三个部分向大家介绍(每日更新): ...
- boost的线程池和内存池 智能指针
内存池为boost自带的 #include <boost/pool/pool.hpp> 或者另外一个开源的库: nedmalloc 一个高效率的库 线程池需要下载另外一个开源库 http: ...
- nginx源码学习----内存池
最近在进行监控平台的设计,之前一直觉得C/C++中最棘手的部分是内存的管理上,远不止new/delete.malloc/free这么简单.随着代码量的递增,程序结构复杂度的提高.各种内存方面的问题悄然 ...
随机推荐
- Colaboratory使用教程
Google Colaboratory 是一个 Google 研究项目,旨在帮助传播机器学习培训和研究成果.它是一个 Jupyter 笔记本环境,不需要进行任何设置就可以使用,并且完全在云端运行.同时 ...
- yarn的常用命令
yarn 安装 npm install -g yarn 查看版本 yarn -v 开始一个新工程 yarn init 与 npm init 一样通过交互式会话创建一个 package.json yar ...
- Scrapy框架架构
ENGINE:引擎,负责各个组件的管理. SPIDERS:各个爬虫文件类.(我们一般要写的代码就是这个). SCHEDULER:调度器,ENGINE将爬虫任务分发给该组件,由该组件调度爬虫任务. DO ...
- Typora远程代码执行漏洞 - CVE-2023-2317
Typora - CVE-2023-2317 简介 Typora一个常用的markdown编辑器,在1.6.7之前存在XSS漏洞,可以通过传入参数触发来加载恶意的JavaScript代码 分析 在ty ...
- 2023.3 Idea配置Tomcat环境
tomcat配置 下载tomcat 先到官网(按住Ctrl再左键点击直接打开官网)下载64位的tomcat,网速慢就用魔法下 创建项目.模块 打开idea(我用的是最新的idea的专业版,ui有点变化 ...
- Python——第二章:字典的循环、嵌套、"解构"(解包)
字典进阶操作 -- 循环和嵌套 字典的循环 我们先看直接打印字典的样子,会分别对每对key:value进行打印,并使用,分隔他们 dic = { "赵四": "特别能歪嘴 ...
- Java异常中处理return
Java中的return语句 在Java中,return语句用于从一个方法中返回结果,并终止当前方法的执行.在方法中使用return语句后,后续的语句将不会执行. public int add(int ...
- KubeFlow-Pipeline及Argo实现原理速析
Argo是一个开源原生容器工作流引擎用于在Kubernetes上开发和运行应用程序.Argo Workflow流程引擎,可以编排容器流程来执行业务逻辑,在20年4月8日进入CNCF孵化器组. 而Kub ...
- 云小课|GaussDB如何进行性能调优
阅识风云是华为云信息大咖,擅长将复杂信息多元化呈现,其出品的一张图(云图说).深入浅出的博文(云小课)或短视频(云视厅)总有一款能让您快速上手华为云.更多精彩内容请单击此处. 摘要:GaussDB性能 ...
- 云图说|应用魔方AppCube:揭秘码农防脱神器
摘要: 应用魔方(AppCube)是华为云为行业客户.合作伙伴.开发者量身打造的一款低代码开发平台.通过AppCube可轻松构建专业级应用,创新随心所欲,敏捷超乎想象. 本文分享自华为云社区<云 ...