如果由操作系统进行管理内存,操作系统在分配和管理内存,应该会存在用户态与核心态的切换,而且会有地址空间的预定和调拨物理存储器等一系列的操作,而这些操作是不可控的,极大的影响了效率。apache自己管理内存,速度是一个重要的原因。
每一连续的内存(逻辑上,物理上的地址空间不一定是)都由内存管理结点,管理着这段内存。内存表示方法是通过下标的进行表示的,如果下标为0,内存大小为(MIN_ALLOC宏定义)为8KB,下标每加1,就是增加4KB的大小。
每个内存管理结点自己所占的内存在分配这块内存的开始处。
<span style="font-size:14px;">struct apr_memnode_t {
apr_memnode_t *next; /**< next memnode 下一个结点*/
apr_memnode_t **ref; /**< reference to self 指向这个结点的next的引用*/
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 指向空闲内存结束处*/
};</span><span style="font-size:12px;">
</span>
把这些内存管理结点用分配器进行管理。ref二级指针的使用方式很巧妙,在内存池中,也会存在。
struct apr_allocator_t { /** 分配器 */
apr_uint32_t max_index; //所能允许的最大的内存结点下标
apr_uint32_t max_free_index;//内存分配器总共所能容纳的最大内存阀值,
apr_uint32_t current_free_index;//该内存器中还可以再管理外面的内存
#if APR_HAS_THREADS
apr_thread_mutex_t *mutex;//多线程的使用
#endif /* APR_HAS_THREADS */
apr_pool_t *owner;//该分配器属于哪个内存池
apr_memnode_t *free[MAX_INDEX];/* 每个指针形成单链表 */
};
#define MIN_ALLOC 8192 //最小分配8K 的内存
#define MAX_INDEX 20
#define BOUNDARY_INDEX 12
#define BOUNDARY_SIZE (1 << BOUNDARY_INDEX)
#define SIZEOF_ALLOCATOR_T APR_ALIGN_DEFAULT(sizeof(apr_allocator_t))