`
soboer
  • 浏览: 1309962 次
文章分类
社区版块
存档分类
最新评论

用文件映射(File Mapping)实现进程间内存共享

 
阅读更多
我们知道,在Windows中的每个进程都有自己独立的内存空间。该独立的内存空间包含了所有的可执行模块或DLL模块的代码和数据以及动态内存分配的空间。每个进程的内存空间只能被该进程访问,其他进程是不能访问的。
如果我们要想在进程间共享内存(也就是创建一块不同进程都能访问的内存),那就必须使用内核对象。因为内核对象由Windows系统内核所拥有,而不是由进程所拥有。
下面就用文件映射(File Mapping)和互斥量(Mutex)两中内核对象来实现简单的进程间内存共享。文件映射(File Mapping)用来开辟共享的内存空间,而互斥量(Mutex)则是用来使读写互斥。
在该例子里,实现了下面5个函数用来进行进程间的内存共享。可以把这5个函数放到一个DLL里面当成输出函数来用。在进程里加载该DLL并调用相应的函数就可实现进程间内存共享。
首先,定义返回值代码:
typedefenum
{
LX_OK
=0,//正常返回
LX_SHAREDMEMORY_EXISTS=1,//共享内存已经存在
LX_INVALID_SHAREDMEMORY=2,//共享内存错误返回
LX_INVALID_SIZE =3//共享内存大小错误
}LX_RETURN_VALUE;
然后,是函数声明:
//创建共享内存
LX_RETURN_VALUECreateSharedMemory(UINTnSize);
//释放共享内存
LX_RETURN_VALUEReleaseSharedMemory();
//得到共享内存大小
LX_RETURN_VALUEGetSharedMemorySize(UINT&nSize);
//向共享内存写入数据
LX_RETURN_VALUEWriteToSharedMemory(void*pData,UINTnSize);
//从共享内存读取数据
LX_RETURN_VALUEReadFromSharedMemory(void*pData,UINTnSize);
下面是函数的实现:
//自动Lock和Unlock互斥量
structCAutoMutex
{
CAutoMutex();
~CAutoMutex();

//互斥量
staticCMutexm_mutex;
};

CMutexCAutoMutex::m_mutex(FALSE,
"StarLeeMutex");

CAutoMutex::CAutoMutex()
{
m_mutex.Lock();
}

CAutoMutex::
~CAutoMutex()
{
m_mutex.Unlock();
}

LX_RETURN_VALUECreateSharedMemory(UINTnSize)
{
//创建共享内存块
HANDLEhFileMapping=CreateFileMapping(INVALID_HANDLE_VALUE,NULL,PAGE_READWRITE,0,nSize,"StarLeeSharedMemory");

//创建错误
if((hFileMapping==NULL)||(hFileMapping==INVALID_HANDLE_VALUE))
returnLX_INVALID_SHAREDMEMORY;

//共享内存已经存在
if(GetLastError()==ERROR_ALREADY_EXISTS)
returnLX_SHAREDMEMORY_EXISTS;

//创建另外一块内存存放共享内存的大小
HANDLEhSize=CreateFileMapping(NULL,NULL,PAGE_READWRITE,0,sizeof(UINT),"StarLeeSharedMemorySize");

if((hSize==NULL)||(hSize==INVALID_HANDLE_VALUE)||(GetLastError()==ERROR_ALREADY_EXISTS))
returnLX_INVALID_SHAREDMEMORY;

//得到存放共享内存大小的指针
UINT*pSize=(UINT*)MapViewOfFile(hSize,FILE_MAP_WRITE,0,0,sizeof(UINT));

if(pSize==NULL)
returnLX_INVALID_SHAREDMEMORY;

//写入共享内存的大小
memcpy(pSize,&nSize,sizeof(UINT));

UnmapViewOfFile(pSize);

returnLX_OK;
}

LX_RETURN_VALUEReleaseSharedMemory()
{
CAutoMutexMutexLock;

//打开共享内存
HANDLEhFileMapping=OpenFileMapping(FILE_MAP_ALL_ACCESS,FALSE,"StarLeeSharedMemory");

//关闭共享内存
if(hFileMapping!=NULL)
CloseHandle(hFileMapping);

//打开存放共享内存大小的文件映射
HANDLEhSize=OpenFileMapping(FILE_MAP_ALL_ACCESS,FALSE,"StarLeeSharedMemorySize");

//关闭存放共享内存大小的文件映射
if(hSize!=NULL)
CloseHandle(hSize);

returnLX_OK;
}

LX_RETURN_VALUEGetSharedMemorySize(UINT
&nSize)
{
CAutoMutexMutexLock;

HANDLEhSize
=OpenFileMapping(FILE_MAP_READ,FALSE,"StarLeeSharedMemorySize");

if(hSize==NULL)
returnLX_INVALID_SHAREDMEMORY;

UINT
*pSize=(UINT*)MapViewOfFile(hSize,FILE_MAP_READ,0,0,sizeof(UINT));

if(pSize==NULL)
returnLX_INVALID_SHAREDMEMORY;

//得到共享内存的大小
memcpy(&nSize,pSize,sizeof(UINT));

returnLX_OK;
}

LX_RETURN_VALUEWriteToSharedMemory(
void*pDate,UINTnSize)
{
UINTnSharedMemorySize
=0;

//得到共享内存的大小
if(GetSharedMemorySize(nSharedMemorySize)!=LX_OK)
returnLX_INVALID_SHAREDMEMORY;

//检查共享内存的大小
if(nSize>nSharedMemorySize)
returnLX_INVALID_SIZE;

CAutoMutexMutexLock;

HANDLEhFileMapping
=OpenFileMapping(FILE_MAP_WRITE,FALSE,"StarLeeSharedMemory");

if(hFileMapping==NULL)
returnLX_INVALID_SHAREDMEMORY;

void*pMapView=MapViewOfFile(hFileMapping,FILE_MAP_WRITE,0,0,nSize);

if(pMapView==NULL)
returnLX_INVALID_SHAREDMEMORY;

//清空共享内存
memset(pMapView,0,nSharedMemorySize);

//将数据写入共享内存
memcpy(pMapView,pDate,nSize);

UnmapViewOfFile(pMapView);

returnLX_OK;
}

LX_RETURN_VALUEReadFromSharedMemory(
void*pData,UINTnSize)
{
UINTnSharedMemorySize
=0;

if(GetSharedMemorySize(nSharedMemorySize)!=LX_OK)
returnLX_INVALID_SHAREDMEMORY;

if(nSize>nSharedMemorySize)
returnLX_INVALID_SIZE;

CAutoMutexMutexLock;

HANDLEhFileMapping
=OpenFileMapping(FILE_MAP_READ,FALSE,"StarLeeSharedMemory");

if(hFileMapping==NULL)
returnLX_INVALID_SHAREDMEMORY;

void*pMapView=MapViewOfFile(hFileMapping,FILE_MAP_READ,0,0,nSize);

if(pMapView==NULL)
returnLX_INVALID_SHAREDMEMORY;

//从共享内存读取数据
memcpy(pData,pMapView,nSize);

UnmapViewOfFile(pMapView);

returnLX_OK;
}
对于代码中能自动锁定和结锁互斥量的结构AutoMutex,可以参考我的《巧用构造函数与析构函数对数据进行设置和恢复》
分享到:
评论

相关推荐

    用内存文件映射实现两进程间的内存共享 (2000年)

    文件映射是两进程共享内存的重要方法。用文件映射实现了USER和NETWORK两进程之间的共享内存,并对其函数和函数的参数进行了解释。

    MemoryMappingFile

    本文分析了Win32 环境下内存映射文件技术的系统实现原理, 并结合嵌入式文件系统的特点, 给出了该技术在嵌入式实时通讯系统中对多进程间数据共享问题的解决方案

    进程之间通信例子,包含接收端和发送端

    3)文件映射(File Mapping):在32位系统中提供的新方法,可用来共享内存 4)远程数据写入/读取 5)管道(Pipe):用于设置应用程序间的一条永久通讯通道,通过该通道可以象自己的应用程序访问一个平面文件一样...

    精通Windows.API-函数、接口、编程实例.pdf

    11.5.2 通过File Mapping在进程间共享数据 333 11.5.3 Windows Socket 333 第12章 Windows Shell程序设计 334 12.1 Windows Shell目录管理 335 12.1.1 Shell对目录和文件的管理形式 335 12.1.2 “我的文档...

    精通WindowsAPI 函数 接口 编程实例

    11.5.2 通过File Mapping在进程间共享数据 333 11.5.3 Windows Socket 333 第12章 Windows Shell程序设计 334 12.1 Windows Shell目录管理 335 12.1.1 Shell对目录和文件的管理形式 335 12.1.2 “我的...

    asp.net知识库

    使用.ashx文件处理IHttpHandler实现发送文本及二进制数据的方法 制作一个简单的多页Tab功能 一完美的关于请求的目录不存在而需要url重写的解决方案! 在C#中实现MSN消息框的功能 XmlHttp实现无刷新三联动ListBox 鼠标...

    精通WindowsAPI.pdf

    1.2.8 使用命令行工具编译.........................................................................................23 第2章 Windows API概要..................................................................

Global site tag (gtag.js) - Google Analytics