如何通过Memory-Mapped Files在多个进程之间共享内存?

zengkun100 2005-07-12 05:20:04
现在有一个DLL,这个DLL内部有一个C++对象将在多个使用该DLL的进程间共享。查了MSDN之后知道,为了在进程间共享DLL内部的C++对象,唯一的办法就是用Memory-Mapped Files。

我的做法当然是在DLL的内部CreateFileMapping,然后MapViewOfFile,取出共享的内存,如果是第一个加载该DLL的进程,就初始化C++对象。当第二个进程再调用CreateFileMapping函数时,通过GetLastError函数就知道内存映像已经创建,直接取C++对象来用。

但是:问题的关键就在于:第一次创建内存映像时,需要指定内存大小,我用的是C++类的大小,但是该C++对象内部有一个指针类型的成员变量,第一个加载DLL的进程会初始化该指针,这样就只能在第一个加载DLL的进程内部使用该C++对象了。当第二个进程加载DLL时,它试图取到那个C++对象,但是,因为指针的原因,会出现拒绝访问。

请问:如何解决这个问题——如果我要在进程之间共享一个含有指针类型成员变量的C++对象,该怎么办?

创建内存映像的代码如下:
g_HSchema = CreateFileMapping(
(HANDLE)0xFFFFFFFF,
NULL,
PAGE_READWRITE,
0,
sizeof(g_Schema),
"mappedmemmoryforschema");
if(!g_HSchema)
{
DWORD errcode = GetLastError();
throw dll_error("在InitializeDll中创建内存文件映像出错!");
}
bool isFirstInit = (ERROR_ALREADY_EXISTS != GetLastError());
g_pSchema = MapViewOfFile(
g_HSchema,
FILE_MAP_WRITE,
0,
0,
0);
if(!g_pSchema)
{
DWORD errcode = GetLastError();
throw dll_error("取内存文件映像时出错!");
}
ISchemaPtr* MemoryMappedSchema = (ISchemaPtr*)g_pSchema;
if(isFirstInit) //如果是首次加载Schema文件到内存
{
IXMLDOMSchemaCollection2Ptr SchemaCollection;
HRESULT hr = SchemaCollection.CreateInstance(__uuidof(XMLSchemaCache40));
if(FAILED(hr))
throw dll_error("InitializeDll中CreateInstance失败!");
try
{
SchemaCollection->add("http://www.mapgis.cn", "sample.xsd");
}
catch(_com_error)
{
throw dll_error("DLL在加载Schema文件时出现致命错误!请检查Schema文件!");
}
*MemoryMappedSchema = SchemaCollection->getSchema("http://www.mapgis.cn"); //初始化内存映象
//上一步会初始化C++类里的那个指针类型的成员变量
}
g_Schema = *MemoryMappedSchema; //第一个进程到这里挺好,第二个进程到这里会出现拒绝访问。
...全文
368 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
ljlln 2005-07-18
  • 打赏
  • 举报
回复
我认为和指针没有多大的关系。你既然已经写入文件了。释放你的指针也是没有关系的。在其他要使用该对象的地方(其他进程)中重新创建一个对象,然后用内存映射文件的内容初始化新创建的对象。应该可以吧
zengkun100 2005-07-16
  • 打赏
  • 举报
回复
ljlln(阿明)
这个对象当然已经写到内存映象文件中去了,但是,这个对象中有个指针,这个指针指向的内存在一个进程中初始化,在另一个进程中是访问不了的呀!

是不是这个设计本身有问题呀?有没有解决办法?
hollysky 2005-07-15
  • 打赏
  • 举报
回复
这是很自然的问题啊。
该对象中的指针所向的对象地址空间是在另一个进程空间。
所以被指针所指的对象也必须在共享内存范围内,而且只能用偏移量来标志。
ljlln 2005-07-15
  • 打赏
  • 举报
回复
你把你的对象写入内存映射文件中。在其他进程中读取内存映射文件来初始化一个对象。不是达到共享的目的了吗
oyljerry 2005-07-14
  • 打赏
  • 举报
回复
考虑不直接用对象,换别的方法来操作需要共享的咚咚
zengkun100 2005-07-13
  • 打赏
  • 举报
回复
自己顶一把
zengkun100 2005-07-12
  • 打赏
  • 举报
回复
总觉得CSDN对代码支持不够,上面的代码真是丑呀!辛苦大家了!

15,471

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 进程/线程/DLL
社区管理员
  • 进程/线程/DLL社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧