`
yangyou230
  • 浏览: 1647874 次
文章分类
社区版块
存档分类

ACE内存映射技术

 
阅读更多

内存映射文件

多个操作系统平台都提供了内存映射文件,这是一个简单的将数据结构保存到文件中的机制。同时由于32位操作系统的进程虚拟内存最大只能4GB,用内存映射文件的方式就可以突破这个限制,可以用来打开超过4GB的大文件。

而且,内存映射文件其实就是一种共享内存机制,进程间可以通过共享内存直接访问数据。

ACE提供了ACE_MMAP_Memory_Pool类,该类代表了为内存映射文件分配内存的内存池。和ACE_Malloc模板类配合,我们就可以以平台无关的方式操纵内存映射文件了。比如:ACE_Malloc<ACE_MMAP_Memory_Pool,ACE_SYNCH_MUTEX> 。第二个参数是并发锁的策略类。

下面的例子实现了write函数,该函数负责将结构SHMRecord的数据写到内存映射文件snapshot中,并且以HashMap的方式保存。key是offset的字符串表示,value是结构的指针。

注意,结构中的pData_成员指向的内存也应该由ACE_Malloc在内存映射文件中分配。这种模式下,千万用常规思路管理内存回收,比如智能指针,有时候内存不需要回收。

#include <iostream>

#include <sstream>

using namespace std;

#include "ace/MMAP_Memory_Pool.h"

#include "ace/Malloc_T.h"




class SHMRecord

{

public:

SHMRecord():pData_(NULL){}

ACE_UINT16 type_;

ACE_UINT32 offset_;

void* pData_;

ACE_UINT32 dataLength_;


size_t size() const

{

return 2+4+4+dataLength_;

}

};



typedef

ACE_Malloc<ACE_MMAP_Memory_Pool,ACE_SYNCH_MUTEX> MAllocator;


void write()

{

MAllocator allocator("/opt/ace/freebird/snapshot");


void * pMemory=allocator.malloc(sizeof(SHMRecord));

if(pMemory==NULL)

{

cout<<"malloc failed"<<endl;

return;

}

SHMRecord* pRecord=new(pMemory) SHMRecord();

pRecord->type_=9;

pRecord->offset_=2;

pRecord->dataLength_=4;

pRecord->pData_=allocator.malloc(4);

ACE_OS::strcpy(static_cast<char*>(pRecord->pData_),"hel");


stringstream stream;

stream<<pRecord->offset_;

if(allocator.bind(stream.str().c_str(),pRecord)==-1)

{

cout<<"bind failed"<<endl;

return;

}


allocator.sync();

}


void read()

{

}


int main(void)

{

write();

read();

return 0;

}


ACE_Malloc模板类的malloc成员负责分配内存,free负责释放内存,bind负责将数据添加到HashMap中,sync负责将数据从内存写到文件中。构造函数接收文件名作为参数。

现在我们来完成read函数,该函数将负责从内存映射文件中读取数据,并且显示出来。

void read()

{

MAllocator allocator("/opt/ace/freebird/snapshot");


ACE_Malloc_LIFO_Iterator<ACE_MMAP_Memory_Pool,ACE_SYNCH_MUTEX> iter(allocator);


for(void* pData=0;iter.next(pData)!=0;iter.advance())

{

SHMRecord* pRecord=ACE_reinterpret_cast(SHMRecord*,pData);

cout<<pRecord->type_<<endl;

cout<<pRecord->offset_<<endl;

cout<<static_cast<char*>(pRecord->pData_)<<endl;

cout<<pRecord->dataLength_<<endl;

}

}

这里使用了一个后进先出的迭代器,可以遍历HashMap中的数据。当然也可以使用find方法查找指定的数据。

多个进程因而可以使用同一块共享内存,但是问题是这些内存在每个进程中的基地址可能不同。虽然大多数操作系统能够保证,但是万一遇到意外情况怎么办?在这种情况下直接保存的指针将毫无意义。


ACE提供了解决方案:

1)使用ACE_Malloc_T<ACE_MMAP_MEMORY_POOL,

ACE_NUll_Mutex,ACE_PI_Control_Block>代替前面的分配器。关键在于ACE_PI_Control_Block类,该类使我们获得了于位置无关的分配内存功能。

2)在我们的结构中使用了普通的C++指针,现在要替换成ACE_Based_Pointer_Basic<char>类型。 该类会针对不同的基地址重新计算指针。

3)迭代器也应该使用父类:

ACE_Malloc_LIFO_Iterator_T<ACE_MMAP_Memory_Pool,ACE_SYNCH_MUTEX,ACE_PI_Control_Block> iter(allocator);

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics