用文件映射(File Mapping)实现进程间内存共享
2007-06-05 18:13
676 查看
引用自:http://blog.csdn.net/starlee/archive/2007/06/01/1633762.aspx
我们知道,在Windows中的每个进程都有自己独立的内存空间。该独立的内存空间包含了所有的可执行模块或DLL模块的代码和数据以及动态内存分配的空间。每个进程的内存空间只能被该进程访问,其他进程是不能访问的。
如果我们要想在进程间共享内存(也就是创建一块不同进程都能访问的内存),那就必须使用内核对象。因为内核对象由Windows系统内核所拥有,而不是由进程所拥有。
下面就用文件映射(FileMapping)和互斥量(Mutex)两中内核对象来实现简单的进程间内存共享。文件映射(FileMapping)用来开辟共享的内存空间,而互斥量(Mutex)则是用来使读写互斥。Windows,实际上只有映像文件共享内存一种。
在该例子里,实现了下面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);
下面是函数的实现:
//互斥量
CMutexg_mMutex(FALSE,"StarLeeMutex");
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()
{
g_mMutex.Lock();
//打开共享内存
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);
g_mMutex.Unlock();
returnLX_OK;
}
LX_RETURN_VALUEGetSharedMemorySize(UINT&nSize)
{
g_mMutex.Lock();
HANDLEhSize=OpenFileMapping(FILE_MAP_READ,FALSE,"StarLeeSharedMemorySize");
if(hSize==NULL)
{
g_mMutex.Unlock();
returnLX_INVALID_SHAREDMEMORY;
}
UINT*pSize=(UINT*)MapViewOfFile(hSize,FILE_MAP_READ,0,0,sizeof(UINT));
if(pSize==NULL)
{
g_mMutex.Unlock();
returnLX_INVALID_SHAREDMEMORY;
}
//得到共享内存的大小
memcpy(&nSize,pSize,sizeof(UINT));
g_mMutex.Unlock();
returnLX_OK;
}
LX_RETURN_VALUEWriteToSharedMemory(void*pDate,UINTnSize)
{
g_mMutex.Lock();
UINTnSharedMemorySize=0;
//得到共享内存的大小
if(GetSharedMemorySize(nSharedMemorySize)!=LX_OK)
returnLX_INVALID_SHAREDMEMORY;
//检查共享内存的大小
if(nSize>nSharedMemorySize)
returnLX_INVALID_SIZE;
HANDLEhFileMapping=OpenFileMapping(FILE_MAP_WRITE,FALSE,"StarLeeSharedMemory");
if(hFileMapping==NULL)
{
g_mMutex.Unlock();
returnLX_INVALID_SHAREDMEMORY;
}
void*pMapView=MapViewOfFile(hFileMapping,FILE_MAP_WRITE,0,0,nSize);
if(pMapView==NULL)
{
g_mMutex.Unlock();
returnLX_INVALID_SHAREDMEMORY;
}
//将数据写入共享内存
memcpy(pMapView,pDate,nSize);
UnmapViewOfFile(pMapView);
g_mMutex.Unlock();
returnLX_OK;
}
LX_RETURN_VALUEReadFromSharedMemory(void*pData,UINTnSize)
{
g_mMutex.Lock();
UINTnSharedMemorySize=0;
if(GetSharedMemorySize(nSharedMemorySize)!=LX_OK)
returnLX_INVALID_SHAREDMEMORY;
if(nSize>nSharedMemorySize)
returnLX_INVALID_SIZE;
HANDLEhFileMapping=OpenFileMapping(FILE_MAP_READ,FALSE,"StarLeeSharedMemory");
if(hFileMapping==NULL)
{
g_mMutex.Unlock();
returnLX_INVALID_SHAREDMEMORY;
}
void*pMapView=MapViewOfFile(hFileMapping,FILE_MAP_READ,0,0,nSize);
if(pMapView==NULL)
{
g_mMutex.Unlock();
returnLX_INVALID_SHAREDMEMORY;
}
//从共享内存读取数据
memcpy(pData,pMapView,nSize);
UnmapViewOfFile(pMapView);
g_mMutex.Unlock();
returnLX_OK;
}
用到的主要接口有:
TheCreateFileMappingfunctioncreatesoropensanamedorunnamedfilemappingobjectforthespecifiedfile.
TheMapViewOfFilefunctionmapsaviewofafileintotheaddressspaceofthecallingprocess.
Tospecifyasuggestedbaseaddress,usetheMapViewOfFileExfunction.
LPVOIDMapViewOfFile(HANDLEhFileMappingObject,DWORDdwDesiredAccess,DWORDdwFileOffsetHigh,DWORDdwFileOffsetLow,SIZE_TdwNumberOfBytesToMap);
TheOpenFileMappingfunctionopensanamedfilemappingobject.
我们知道,在Windows中的每个进程都有自己独立的内存空间。该独立的内存空间包含了所有的可执行模块或DLL模块的代码和数据以及动态内存分配的空间。每个进程的内存空间只能被该进程访问,其他进程是不能访问的。
如果我们要想在进程间共享内存(也就是创建一块不同进程都能访问的内存),那就必须使用内核对象。因为内核对象由Windows系统内核所拥有,而不是由进程所拥有。
下面就用文件映射(FileMapping)和互斥量(Mutex)两中内核对象来实现简单的进程间内存共享。文件映射(FileMapping)用来开辟共享的内存空间,而互斥量(Mutex)则是用来使读写互斥。Windows,实际上只有映像文件共享内存一种。
在该例子里,实现了下面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);
下面是函数的实现:
//互斥量
CMutexg_mMutex(FALSE,"StarLeeMutex");
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()
{
g_mMutex.Lock();
//打开共享内存
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);
g_mMutex.Unlock();
returnLX_OK;
}
LX_RETURN_VALUEGetSharedMemorySize(UINT&nSize)
{
g_mMutex.Lock();
HANDLEhSize=OpenFileMapping(FILE_MAP_READ,FALSE,"StarLeeSharedMemorySize");
if(hSize==NULL)
{
g_mMutex.Unlock();
returnLX_INVALID_SHAREDMEMORY;
}
UINT*pSize=(UINT*)MapViewOfFile(hSize,FILE_MAP_READ,0,0,sizeof(UINT));
if(pSize==NULL)
{
g_mMutex.Unlock();
returnLX_INVALID_SHAREDMEMORY;
}
//得到共享内存的大小
memcpy(&nSize,pSize,sizeof(UINT));
g_mMutex.Unlock();
returnLX_OK;
}
LX_RETURN_VALUEWriteToSharedMemory(void*pDate,UINTnSize)
{
g_mMutex.Lock();
UINTnSharedMemorySize=0;
//得到共享内存的大小
if(GetSharedMemorySize(nSharedMemorySize)!=LX_OK)
returnLX_INVALID_SHAREDMEMORY;
//检查共享内存的大小
if(nSize>nSharedMemorySize)
returnLX_INVALID_SIZE;
HANDLEhFileMapping=OpenFileMapping(FILE_MAP_WRITE,FALSE,"StarLeeSharedMemory");
if(hFileMapping==NULL)
{
g_mMutex.Unlock();
returnLX_INVALID_SHAREDMEMORY;
}
void*pMapView=MapViewOfFile(hFileMapping,FILE_MAP_WRITE,0,0,nSize);
if(pMapView==NULL)
{
g_mMutex.Unlock();
returnLX_INVALID_SHAREDMEMORY;
}
//将数据写入共享内存
memcpy(pMapView,pDate,nSize);
UnmapViewOfFile(pMapView);
g_mMutex.Unlock();
returnLX_OK;
}
LX_RETURN_VALUEReadFromSharedMemory(void*pData,UINTnSize)
{
g_mMutex.Lock();
UINTnSharedMemorySize=0;
if(GetSharedMemorySize(nSharedMemorySize)!=LX_OK)
returnLX_INVALID_SHAREDMEMORY;
if(nSize>nSharedMemorySize)
returnLX_INVALID_SIZE;
HANDLEhFileMapping=OpenFileMapping(FILE_MAP_READ,FALSE,"StarLeeSharedMemory");
if(hFileMapping==NULL)
{
g_mMutex.Unlock();
returnLX_INVALID_SHAREDMEMORY;
}
void*pMapView=MapViewOfFile(hFileMapping,FILE_MAP_READ,0,0,nSize);
if(pMapView==NULL)
{
g_mMutex.Unlock();
returnLX_INVALID_SHAREDMEMORY;
}
//从共享内存读取数据
memcpy(pData,pMapView,nSize);
UnmapViewOfFile(pMapView);
g_mMutex.Unlock();
returnLX_OK;
}
用到的主要接口有:
TheCreateFileMappingfunctioncreatesoropensanamedorunnamedfilemappingobjectforthespecifiedfile.
HANDLECreateFileMapping( HANDLEhFile, LPSECURITY_ATTRIBUTESlpAttributes, DWORDflProtect, DWORDdwMaximumSizeHigh, DWORDdwMaximumSizeLow, LPCTSTRlpName);
TheMapViewOfFilefunctionmapsaviewofafileintotheaddressspaceofthecallingprocess.
Tospecifyasuggestedbaseaddress,usethe
LPVOIDMapViewOfFile(HANDLEhFileMappingObject,DWORDdwDesiredAccess,DWORDdwFileOffsetHigh,DWORDdwFileOffsetLow,SIZE_TdwNumberOfBytesToMap);
TheOpenFileMappingfunctionopensanamedfilemappingobject.
HANDLEOpenFileMapping(
DWORDdwDesiredAccess,
BOOLbInheritHandle,
LPCTSTRlpName);
相关文章推荐
- 用文件映射(File Mapping)实现进程间内存共享
- 用文件映射(File Mapping)实现进程间内存共享
- 用文件映射(File Mapping)实现进程间内存共享
- 用文件映射(File Mapping)实现进程间内存共享[转]
- 用文件映射(File Mapping)实现进程间内存共享
- 用文件映射(File Mapping)实现进程间内存共享
- UNIX环境高级编程学习之第十五章进程间通信 - 两个进程通过映射普通文件实现共享内存通信
- 通过内存映射文件实现进程间数据共享
- 利用内存映射文件在进程间共享数据
- c++ 内存映射文件进程间共享数据
- 利用内存映射文件在进程间共享数据
- windows 内存映射文件实现数据共享之原理
- C# .Net 多进程同步 通信 共享内存 内存映射文件 Memory Mapped
- c#实现内存映射文件共享内存
- 利用内存映射文件在进程间共享数据
- C# .Net 多进程同步 通信 共享内存 内存映射文件 Memory Mapped
- 使用内存映射文件在进程之间共享数据
- 利用内存映射文件在两个进程间共享数据
- windows下利用文件映射实现共享内存
- 进程间通过内存映射文件共享数据