| 通常程序下,C语
言中内存的分配与
释
放是用
malloc与free。缺点很多,
开发
者可能因
为
疏忽而忘
记释
放。在
Apache
这样
的服
务
器中如果内存有泄漏是
|
| 不可被容忍的。而且频繁的malloc与free可能会造成页面错误。如果一直不释放会造成系统性能下降。
| | | | | | | | | | | | | | | | |
| 因此Apache引入了内存池概念。内存池是一片很大的内存空间,一次性分配成功避免反
复的申
请释放。而且内存的释放会在内存销
毁的
时候释放。
|
| 但如果内存池只有一个的话,那
么
这个内存池需要在Apache启动的时候申请,在Apache关闭的时候释放。这样显得不太合理。
| | | | | |
| 因此Apache会使用多个内存池,采用分级的方法,
每一
级内存池的生命周期不同。
| | | | | | | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| 首先,我需要了解一下Apache代码的结构:
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | apache可划分为四大层次:可移植运行库(
APR)、核心功能
层(
Apache CORE)、可
选功能层(
Apache Optional Module)、第三方支持
库。
| | |
| | 图例: | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | | | | | | | | Apche模块
中的第三方支持
库
| | | | | | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | OpenSSL
PHP …………………………………………………………………Perl LDAP | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | | | | | | | | | | | Apche可选
功能
层
| | | | | | | | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | mod_SSL mod_Php
mod_rewrite ………………………………………mod_perl mod_ladp | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | | | | | | | | | Apche核心功能层
| | | | | | | | | | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | http_core
http_request……http_protocol(Apache核心)
mod_so core MPM http(核心模块)
| | | | | | | | |
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | | | | | | | | | libapr库
(可移
值
运行
库层
)
| | | | | | | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | 共享内存 文件I/O 网络
I/O……
libpcre libldap
libexpat
| | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | | | | | | 操作系统
(Win32、Unix、OS/2、MacOS、Netware)
| | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | 因为OS不同,apache在处理跨平台的时候显然需要使用不同的系统API。从2.0开始,Apache将专门封装不同操作系统API的任务分离了出来,形成APR。
|
| | | 这样对于所有的操作系统,提供了一个完全相同的函数接口。这样事实上,任何应用程序想要跨平台均可使用APR做为底层的支持。 | | |
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| 其次,我需要了解一下内存池的分级情况:
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | | | | | | | | |
| | | | | | | |
| | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | |
| | | 但需要注意的是pool并不会直接分配与释放内存,而是通过
allocator来
统一管理。
Pool采用的是
树形结构,如上图所示。在内存初始化时,使用函数
|
| | | apr_pool_initialize建立根池与全局的allocator,以后建立的都是根结点的子孙结点。可以从
pool中分配任何大小的内存。但需要在
释放
pool
时这些申请的内存
|
| | | 才会被释放。需要注意 的是,有些分配的内存块,清除时有特别的操作,所以需要自带清除函数,在分配之后用apr_pool_cleanup_register注册清除时用的
|
| | | 函数。特殊的是,如果内存块里是线程对象,不能用一般的清除函数,应该用apr_pool_note_subprocess注册清除操作。
| | | | | | | | |
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| 接下来,需要看一下池的结
构:(以下内容,摘自http://blog.youkuaiyun.com/fastxyf/archive/2006/06/30/855344.aspx)需要
亲自对代码中看一下。
| | |
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | //池的结
构
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | struct apr_pool_t { | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | |
apr_pool_t
*parent;
//父池结
点
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | |
apr_pool_t
*child;
//子池结
点
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | |
apr_pool_t
*sibling;
//兄弟池结
点
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | |
apr_pool_t
**ref;
//指向-指向自已的指针
,一般是前
继结
点的next指
针
| | | | | | | | | | | | | | | | | | | | |
| | |
cleanup_t
*cleanups;
//需要清除函数来销
毁
的内存
块
指
针
列表,通
过
注册来加入的
| | | | | | | | | | | | | | | |
| | |
cleanup_t
*free_cleanups;//当Kill
cleanups中的一个项时
,放到
这
里,注册一个新的
项时
,先从
这
里利用
| | | | | | | | | |
| | |
apr_allocator_t
*allocator;
//内存分配器,一般就用默认
的,所有池共享一个内存分配器
| | | | | | | | | | | | | | | | |
| | |
struct process_chain *subprocesses; //子线
程
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | |
apr_abortfunc_t
abort_fn;
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | |
apr_hash_t
*user_data; | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | |
const char
*tag; | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | #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_status_t
apr_pool_initialize (void) | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | 销毁
内存池
对
象,及内部的
结
构和子内存池
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | void
apr_pool_terminate (void) | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | 创建一个新的内存池
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | apr_status_t
apr_pool_create_ex (apr_pool_t
**newpool, apr_pool_t *parent, apr_abortfunc_t abort_fn, apr_allocator_t
*allocator) | | | | |
| | | 创建一个新的内存池,apr_pool_create_ex的使用默
认
参数
简
化版
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | apr_status_t
apr_pool_create (apr_pool_t **newpool,
apr_pool_t *parent) | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | 获取内存池使用的内存分配器
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | apr_allocator_t *
apr_pool_allocator_get (apr_pool_t
*pool) | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | 清除一个内存池的内容,清除后内容为
空,但可以再使用
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | void
apr_pool_clear (apr_pool_t *p) | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | 释构一个内存池
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | void
apr_pool_destroy (apr_pool_t *p) | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | 从池中分配内存 | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | void *
apr_palloc (apr_pool_t *p,
apr_size_t size) | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | 从池中分配内存,并将分配出来的内存置0 | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | void *
apr_pcalloc (apr_pool_t *p,
apr_size_t size) | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | 设置内存分配出
错时
的
调
用函数
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | void
apr_pool_abort_set
(apr_abortfunc_t abortfunc, apr_pool_t *pool) | | | | | | | | | | | | | | | | | | | | | | | | |
| | | 获取内存分配出
错时
的
调
用函数
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | apr_abortfunc_t
apr_pool_abort_get (apr_pool_t *pool) | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | 获取池的父池
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | apr_pool_t *
apr_pool_parent_get (apr_pool_t *pool) | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | 判断a是否是b的祖先 | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | int
apr_pool_is_ancestor (apr_pool_t
*a, apr_pool_t *b) | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | 为内存池做
标签
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | void
apr_pool_tag (apr_pool_t *pool,
const char *tag) | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | 设置与当前池
关联
的数据
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | apr_status_t
apr_pool_userdata_set (const void *data,
const char *key, apr_status_t(*cleanup)(void *), apr_pool_t *pool) | | | | | | | |
| | | 设置与当前池
关联
的数据,与apr_pool_userdata_set
类
似,但内部不拷
贝
数据的
备
份,如常量字符串
时
就有用
| | | | | | | | | | | | | |
| | | apr_status_t
apr_pool_userdata_setn (const void
*data, const char *key, apr_status_t(*cleanup)(void *), apr_pool_t *pool) | | | | | | |
| | | 获取与当前池
关联
的数据
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | apr_status_t
apr_pool_userdata_get (void **data,
const char *key, apr_pool_t *pool) | | | | | | | | | | | | | | | | | | | | | |
| | | 注册内存块
的清除函数,
每
块销
毁
时
要特
别处
理的都要注册下,在cleanups里加入一个
项
| | | | | | | | | | | | | | | | | | | |
| | | void
apr_pool_cleanup_register
(apr_pool_t *p, const void *data, apr_status_t(*plain_cleanup)(void *),
apr_status_t(*child_cleanup)(void *)) |
| | | 删除内存
块
的清除函数,从cleanups里移除一个
项
,放入free_cleanups中
| | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | void
apr_pool_cleanup_kill
(apr_pool_t *p, const void *data, apr_status_t(*cleanup)(void *)) | | | | | | | | | | | | | | | | |
| | | 用新的child_cleanup,替换
原来老的child_cleanup
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | void
apr_pool_child_cleanup_set
(apr_pool_t *p, const void *data, apr_status_t(*plain_cleanup)(void *),
apr_status_t(*child_cleanup)(void *)) |
| | | 执行内存
块
的清除函数,
进
从清除函数的
队
列cleanups中
删
除
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | apr_status_t
apr_pool_cleanup_run (apr_pool_t *p,
void *data, apr_status_t(*cleanup)(void *)) | | | | | | | | | | | | | | | | | |
| | | 一个空的内存块
清除函数
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | apr_status_t
apr_pool_cleanup_null (void *data) | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | 执行所有的子清除函数child_cleanup
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | void
apr_pool_cleanup_for_exec (void) | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | 带调试信息内存池函数,功能跟上面的一
样
,只是多了
调试
信息
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | apr_status_t
apr_pool_create_ex_debug (apr_pool_t
**newpool, apr_pool_t *parent, apr_abortfunc_t abort_fn, apr_allocator_t
*allocator, const char *file_line) |
| | | void
apr_pool_clear_debug (apr_pool_t
*p, const char *file_line) | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | void
apr_pool_destroy_debug
(apr_pool_t *p, const char *file_line) | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | void *
apr_palloc_debug (apr_pool_t *p,
apr_size_t size, const char *file_line) | | | | | | | | | | | | | | | | | | | | | |
| | | void *
apr_pcalloc_debug (apr_pool_t
*p, apr_size_t size, const char *file_line) | | | | | | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | 以下描述的应该是apache初始化内存池的一系统操作:
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | <一>内存池初始化
apr_pool_initialize | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | 1.一个进
程只在第一次
调
用
时
初始化,后面只
记录调
用的次数
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | |
if (apr_pools_initialized++) | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | |
return APR_SUCCESS; | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | 2.创
建全局内存分配器(global_allocator)
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | |
if ((rv =
apr_allocator_create(&global_allocator)) != APR_SUCCESS) { | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | |
apr_pools_initialized = 0; | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | |
return rv; | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | |
} | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | 3.创
建全局内存池,根内存池
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | |
if ((rv =
apr_pool_create_ex(&global_pool, NULL, NULL, | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | |
global_allocator)) != APR_SUCCESS) { | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | |
apr_allocator_destroy(global_allocator); | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | |
global_allocator = NULL; | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | |
apr_pools_initialized = 0; | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | |
return rv; | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | |
} | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | 4.为
内存池做
标记
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | |
apr_pool_tag(global_pool,
"apr_global_pool"); | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | 5.初始化原子操作 | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | 6.对
于支持多
线
程的系
统
,
还创
建互拆体,并
设
置到内存分配器
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | #if APR_HAS_THREADS | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | |
{ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | |
apr_thread_mutex_t *mutex; | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | |
if ((rv =
apr_thread_mutex_create(&mutex, | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | |
APR_THREAD_MUTEX_DEFAULT, | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | |
global_pool)) != APR_SUCCESS) { | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | |
return rv; | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | |
} | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | |
apr_allocator_mutex_set(global_allocator, mutex); | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | |
} | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | #endif /*
APR_HAS_THREADS */ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | 7.设
置内存分配器的池所有者
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | |
apr_allocator_owner_set(global_allocator,
global_pool); | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | <二>销
毁
内存池
对
象 apr_pool_terminate
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | 1.如果调
用了多次内存池初始化,
则
只有在
调
用了相
应
次数的
销
毁
时
,最后一次才
进
行操作
| | | | | | | | | | | | | | | | | | | |
| | |
if (!apr_pools_initialized) | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | |
return; | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | |
if (--apr_pools_initialized) | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | |
return; | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | 2.释
放全局内存池,同
时
会
释
放想
应
的互拆体,如果内存分配器的所有者是本内存池,
则
一同
释
放内存分配器
| | | | | | | | | | | | |
| | |
apr_pool_destroy(global_pool); | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | <三>创
建一个新的内存池 apr_pool_create_ex
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | 参数说
明:
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | |
newpool
新创
建的内存池指
针
,用于返回的.
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | |
parent
父内存池. 如果为
空,
则
父内存池
为
根内存池,非空
时
,新的内存池
继
承父内存池的属性.
| | | | | | | | | | | | | | |
| | |
abort_fn
分配内存失败时
的回
调
函数,中断函数
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | |
allocator
新内存池所用的内存分配器. NULL则
使用父内存池的内存分配器
| | | | | | | | | | | | | | | | | | | | | | |
| | | 1.先确定内存池的参数,如父结
点,出
错处
理函数,所用的内存分配器
| | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | |
if (!parent) | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | |
parent = global_pool; | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | |
if (!abort_fn && parent) | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | |
abort_fn = parent->abort_fn; | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | |
if (allocator == NULL) | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | |
allocator = parent->allocator; | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | 2.从内存分配器一块
内存
块
,用于存
贮
内存池的信息,如果内存分配失
败
,
则调
用中断函数
| | | | | | | | | | | | | | | | | | | | |
| | |
if ((node = allocator_alloc(allocator, | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | |
MIN_ALLOC -
APR_MEMNODE_T_SIZE)) == NULL) { | | | | | | | | | | | | | | | | | | | | | | | | |
| | |
if (abort_fn) | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | |
abort_fn(APR_ENOMEM); | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | |
return APR_ENOMEM; | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | |
} | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | 3.用新分配内存块
,存
贮
内存池的
结
构apr_pool_t
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | |
node->next = node; | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | |
node->ref = &node->next; | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | |
pool = (apr_pool_t
*)node->first_avail; | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | |
node->first_avail =
pool->self_first_avail = (char *)pool + SIZEOF_POOL_T; | | | | | | | | | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | |
pool->allocator = allocator; | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | |
pool->active = pool->self = node; | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | |
pool->abort_fn = abort_fn; | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | |
pool->child = NULL; | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | |
pool->cleanups = NULL; | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | |
pool->free_cleanups = NULL; | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | |
pool->subprocesses = NULL; | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | |
pool->user_data = NULL; | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | |
pool->tag = NULL; | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | |
物理内存块
的内容如下
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | |
|----------------| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | |
| apr_memnode_t
| 占用大小 APR_MEMNODE_T_SIZE | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | |
| ---------------| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | |
| apr_pool_t
| 占用大小 SIZEOF_POOL_T | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | |
| ---------------| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | |
|
可用空间
| 占用大小 8K - APR_MEMNODE_T_SIZE -
SIZEOF_POOL_T
| | | | | | | | | | | | | | | | | | | | | |
| | |
| ---------------| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | 4.系统
支持多
线
程,
则创
建互拆体.
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | 5.设
置兄弟
结
点,及父
结
点
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | |
if ((pool->sibling =
parent->child) != NULL) | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | |
pool->sibling->ref =
&pool->sibling; | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | |
parent->child = pool; | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | |
pool->ref = &parent->child; | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | apr_pool_create 是使用了默认
的内存分配器,和中断函数的apr_pool_create_ex
简
化版
| | | | | | | | | | | | | | | | | | | | | |
| | | #define
apr_pool_create(newpool, parent) / | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | |
apr_pool_create_ex(newpool, parent, NULL,
NULL) | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | <四> 从池中分配一块
内存 apr_palloc
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | 参数说
明:
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| |
pool
要分配内存的池 | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| |
size
要分配的内存大小 | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | 1.先按8字节对齐
size
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| |
size = APR_ALIGN_DEFAULT(size); | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | 2. 如果首结
点有足
够
的空
闲
空
间
,
则
从
这
里分配
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| |
if (size <
(apr_size_t)(active->endp - active->first_avail)) { | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| |
mem = active->first_avail; | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| |
active->first_avail += size; | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| |
return mem; | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| |
} | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | 3.跟链
表首
结
点比
较
(因
为链
表
结
点是按空
闲
空
间
的大小,由多至少排序的,所以首
结
点不
够
,后面的也不用比了),空
间够
就从
链
表
头结
点分配,因
为
分配后
链
表
头结
点空
闲
空
间
不一定
还
最多了,所以要取出,后面重新插入
|
| |
如果链
表首
结
点空
间
不
够
,
则调
用内存分配器,新分配一
块
内存
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| |
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| |
if (size < (apr_size_t)(node->endp
- node->first_avail)) { | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| |
list_remove(node); | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| |
} | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| |
else { | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| |
if ((node =
allocator_alloc(pool->allocator, size)) == NULL) { | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| |
if (pool->abort_fn) | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| |
pool->abort_fn(APR_ENOMEM); | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| |
return NULL; | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| |
} | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| |
} | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | 4.将首结
点或新分配的
结
点node,插到
队
列首部,再根据node里的空
间
大小,
选择
插到的位置
| | | | | | | | | | | | | | | | | | | | |
| |
这
里没看懂,
为
什
么
要插入?到后面找又先移出,再插到正确位置.不能改成直接在后面一次插入?
| | | | | | | | | | | | | | | | |
| |
list_insert(node, active); | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| |
pool->active = node; | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| |
free_index = (APR_ALIGN(active->endp -
active->first_avail + 1, | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| |
BOUNDARY_SIZE) -
BOUNDARY_SIZE) >> BOUNDARY_INDEX; | | | | | | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| |
active->free_index =
(APR_UINT32_TRUNC_CAST)free_index; | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| |
node = active->next; | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| |
if (free_index >= node->free_index) | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| |
return mem; | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| |
do { | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| |
node = node->next; | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| |
} | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| |
while (free_index <
node->free_index); | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| |
list_remove(active); | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| |
list_insert(active, node); | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | apr_pcalloc
是在apr_palloc分配的内存上,增加了对
分配的内存
块
置0
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| |
size = APR_ALIGN_DEFAULT(size); | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| |
if ((mem = apr_palloc(pool, size)) !=
NULL) { | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| |
memset(mem, 0, size); | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| |
} | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | <五>清空池内容,释
放占用的内存,但保留池
对
象 apr_pool_clear
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | 1.如果存在子池,则释
放所有子池
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| |
while (pool->child) | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| |
apr_pool_destroy(pool->child); | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | 2.调
用清除函数,清除注册了
销
毁
函数的内存
块
,
每
块
需要
销
毁
函数的内存
块
都要
单
独注册
| | | | | | | | | | | | | | | | | | | | |
| |
run_cleanups(&pool->cleanups); | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | 3.清除包括子线
程的内存
块
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| |
free_proc_chain(pool->subprocesses); | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | 4.清除附在本内存池上的内存块
,回到
刚
分配内存池的状
态
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| |
*active->ref = NULL; | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| |
allocator_free(pool->allocator,
active->next); | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| |
active->next = active; | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| |
active->ref = &active->next; | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| <六>释
构一个内存池 apr_pool_destroy
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
执
行的操作和apr_pool_clear差不多,增加了
删
除互拆体,和
释
放内存池
结
构占用的
块
| | | | | | | | | | | | | | | | | | | | | | |
|
如果所用的内存分配器的所有者,是本内存池,也一并析构 | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | 内存池的结构与相关函数了解了以后,应该了解一下内存结点的情况:
| | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | 内存结点是Apache整个内存管理的基础,结构如下:
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | /** basic memory node
structure */ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | struct apr_memnode_t { | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| |
apr_memnode_t *next;
/**< next memnode */ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| |
apr_memnode_t **ref;
/**< reference to self */ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| |
apr_uint32_t
index;
/**< size */ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| |
apr_uint32_t
free_index;
/**< how much free */ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| |
char
*first_avail;
/**< pointer to first free memory
*/ | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| |
char
*endp;
/**< pointer to end of free
memory */ | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | }; | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | 该结构中,不同的结点之间采用next指针形成结点链表。在结点内部为了方便引用自身,成员中加入的ref,主要用来记录当前结点的首地址。 |
| | 该结构中没有存放实际分配的内存,它不会单独存在,依附于具体的内存分配单元。一旦实际内存分配后该结构置于整个单元的顶部。 | | |
| | 如下图示,内存结点的情况:
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | | | | |
| | | | | |
| | | | | | | | | | | |
| | | | | | | | | | | |
| | | | | | | | | | | |
| | | | | | | | | | | |
| | | | | | | | | | | |
| | | | | | | | | | | |
| | | | | | | | | | | |
| | | | | | | | | | | |
| | | | | | | | | | | |
| | | | | | | | | | | |
| | | | | | | | | | | |
| | | | | | | | | | | |
| | | | | | | | | | | |
| | | | | | | | | | | |
| | | | | | | | | | | |
| | | | | | | | | | | |
| | | | | | | | | | | |
| | | | | | | | | | | |
| | | | | | | | | | | |
| | | | | | | | | | | |
| | | | | | | | | | | |
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |