您的位置:首页 > 其它

基于allocator实现的内存共享

2011-02-23 18:20 176 查看
allocator这种模式很早就提出来了,整个STL所有组件的内存均支持从allocator分配。由于allocator的引入,让STL使用者在内存管理策略上有选择的余地,同时又不破坏STL各个组件本身的实现标准。不过allocator这种模式并没有像new&delete取代malloc&free 一样被普及。好在ACE的设计者在对象的内存管理上也沿用了这种思想:1 把策略选择权交给使用者,2 利用模板中的空方法保证未被使用到功能的效率。不过可惜的是ACE::allocator和STL::allocator在接口上并没统一,要在STL容器里能用上ACE的allocator想用还得实现一个bridge的模板类。像这样的一个就行

typedef ACE_Allocator T_MEMORY_ALLOCATOR;
template <class
T> class ACE_STL_ALLOCATOR
{
public:
typedef T value_type;
typedef value_type* pointer;
typedef const value_type* const_pointer;
typedef value_type& reference;
typedef const value_type& const_reference;
typedef std::size_t
size_type;
typedef std::ptrdiff_t
difference_type;
public:
pointer address(reference x) const { return &x; }
const_pointer address(const_reference x)
const {return
&x;}
void construct(pointer p, const value_type&
x) { new(p) value_type(x); }
void destroy(pointer p) { p->~value_type();
}
public:
template <class X>
ACE_STL_ALLOCATOR(const
ACE_STL_ALLOCATOR<X>& other) { m_pAceAllocator = ther.alloctor(); }
template <class X>
struct rebind { typedef ACE_STL_ALLOCATOR<X> other; };
public:
pointer allocate(size_type n, const_pointer = 0) {
void* p = m_pAceAllocator->malloc(n * sizeof(T));
if (!p) throw std::bad_alloc();
return static_cast<pointer>(p); }
void deallocate(pointer p, size_type) {
m_pAceAllocator->free(p); }
size_type max_size()
const {
return static_cast<size_type>(-1) / sizeof(value_type); }
T_MEMORY_ALLOCATOR* alloctor() const { return m_pAceAllocator; }
public:
ACE_STL_ALLOCATOR() : m_pAceAllocator(NULL) {};
ACE_STL_ALLOCATOR(T_MEMORY_ALLOCATOR*
pAceAllocator) : m_pAceAllocator(pAceAllocator){};
protected:
T_MEMORY_ALLOCATOR* m_pAceAllocator;
};

网上详细介绍allocator思想的很多,这里就不再依葫画瓢的描述一遍了,本文想介绍的是使用 ACE
allocator 的体验,以及用它来实现前一篇提到的共享内存系统。

ACE的内存管理策略层次由高到低如下:

适配分配器(Allocator_Adapter)

内存标识及管理(Malloc)

内存池(Memory_Pool)

适配分配器模板
ACE_Allocator_Adapter 接受
ACE_Malloc 或其他类型的
Allocator ,提供统一的对外接口。这个模板主要应用在多个allcator 混合出现的时候,需要在运行时抉择使用哪个。在上篇提到的共享系统里需要区别对待玩家属性和怪物属性,所以在外部创建属性的时候需要传入allcator,这个allcator既可能是管理本地内存也可能是管理共享内存的,这时候只需要把 local_memory_allcator
和 share_memory_allcator塞进 adapter里,统一传递ACE_Allocator*的指针就可以了。上面和STL对接的就是用到的这个,所以理论上stl容器的内存也是可以从共享内存里开辟的。不过实际管理起来和想用共享内存来恢复这个容器又是另一个问题了。

模板类ACE_Malloc接受任意的内存池实现 ACE_XXX_Memory_Pool和互斥体ACE_XXX_Mutex实现作为参数。需要注意的是这个互斥体类只能保护管理器及链表互斥安全,并不保证共享内存对象互斥安全。它所提供的接口:
malloc
(分配)
会在分配的内存前添加MALLOC_HEADER作为管理内存的成本,会从链表中的大块内存中切出想分配的部分并把未合乎要求的内存和切割后剩余部分相连。记录在池中的相邻内存块,做free时的相连操作
calloc(带初始化的分配) 其他内容同上,
free(释放), 利用内存头部的MALLOC_HEADER
推回原来的Pool中,连续内存会相连成一块大的
bind,trybind,unbind
(内存对象绑定一个名字), 将一块内存指针和一个名字保存在一个NAME_NODE中,其中NAME_NODE及名字所占用的内存由
Memory_Pool所分配,意味着如果Memory_Pool为共享内存实现方式,这部分内存开销出现在共享区域
find(通过名字访问内存对象) 实现方式为遍历所有所有bind过的内存,通过NAME_NODE链strcmp 所有注册过的名字
sync(映射同步,只有MMAP内存池真正实现了这个方法)
ACE_Malloc这一层次主要解决的问题就是标识和地址映射的问题,这个需求其实对于本地内存池没啥用。而对于想使用共享内存池的时候就很重要了。毕竟当一个进程刚启动的时候拿到一块内存的时候总得通过标识识别这块内存是用来存什么的。在2个进程访问的时候标识也成为一个唯一能指定提取内存的句柄。在效率上由于bind这类的接口都是交给具体的memory_pool类去实现的,如果是不需要bind的比如local_memory_pool这种提供的是空函数在模板生成的时候自然也都被生成空。
另外ACE_Malloc还提供两种迭代器来遍历所有受管理的内存
后进先出遍历方式:ACE_Malloc_LIFO_Iterator
先进先出遍历方式:ACE_Malloc_FIFO_Iterator
这两种迭代器都是依赖bind 产生的NAME_NODE进行遍历。所以只是malloc出来的内存如果没有bind过是不能通过这种迭代器访问到的。

内存池类Memory_Pool:
原理都一样,从系统那申请一大块内存,然后自己管理。不够用了再按比例申请另一块。ACE针对每种模式和某些特定系统提供了6种现成的类。

ACE_MMAP_Memory_Pool

会在执行程序所在目录产生由管理器同名的文件,不会随着创建进程终止而删除, 异常写入和中断会导致文件不可用。利用ACE_OS::msync把内存映射数据写会磁盘,空函数直接返回

ACE_Lite_MMAP_Memory_Pool

ACE_MMAP_Memory_Pool
的特例,区别在于其中对sync 函数的空实现

ACE_Shared_Memory_Pool
System
V 系列的linux系统可用, windows编译不能

ACE_Pagefile_Memory_Pool
共享内存页实现,目前最接近理想的一种方式,随占用进程的终止而删除(必须由一个进程负责拥有这个内存页,否则被系统回收)

ACE_Local_Memory_Pool
基于标准C 的 new 定义,只能实现基本链表型内存池功能,不能进程间访问,随进程退出而消失

ACE_Sbrk_Memory_Pool
基于标准(sbrk2)实现 的增长型内存策略,windows编译不能

每个Pool需要一个字符命名,这个命名一样也是为了共享区域的标识。由它决定了是不是在同一个共享内存里或是页面映射文件里

基于这套体系。上一篇提到的系统其实很容易只要定义一下
typedef ACE_Allocator_Adapter<ACE_Malloc<ACE_PAGEFILE_MEMORY_POOL,
ACE_Null_Mutex>> TSHARE_MEMORY_ALLOCATOR;
typedef ACE_Allocator_Adapter<ACE_Malloc<ACE_LOCAL_MEMORY_POOL,ACE_Null_Mutex>>
TLOCAL_MEMORY_ALLOCATOR;
利用ACE_Allocator*在系统间传递就行了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: