用内存映射文件在进程中共享数据
来源:互联网 发布:风云排名知乎 编辑:程序博客网 时间:2024/05/01 20:11
用文件映射(File Mapping)实现进程间内存共享
http://blog.csdn.net/starlee/article/details/1633762
我们知道,在Windows中的每个进程都有自己独立的内存空间。该独立的内存空间包含了所有的可执行模块或DLL模块的代码和数据以及动态内存分配的空间。每个进程的内存空间只能被该进程访问,其他进程是不能访问的。
如果我们要想在进程间共享内存(也就是创建一块不同进程都能访问的内存),那就必须使用内核对象。因为内核对象由Windows系统内核所拥有,而不是由进程所拥有。
下面就用文件映射(File Mapping)和互斥量(Mutex)两中内核对象来实现简单的进程间内存共享。文件映射(File Mapping)用来开辟共享的内存空间,而互斥量(Mutex)则是用来使读写互斥。
在该例子里,实现了下面5个函数用来进行进程间的内存共享。可以把这5个函数放到一个DLL里面当成输出函数来用。在进程里加载该DLL并调用相应的函数就可实现进程间内存共享。
首先,定义返回值代码:
typedef enum
{
LX_OK = 0, // 正常返回
LX_SHAREDMEMORY_EXISTS =1,// 共享内存已经存在
LX_INVALID_SHAREDMEMORY =2,// 共享内存错误返回
LX_INVALID_SIZE =3// 共享内存大小错误
}LX_RETURN_VALUE;
{
LX_OK = 0, // 正常返回
LX_SHAREDMEMORY_EXISTS =1,// 共享内存已经存在
LX_INVALID_SHAREDMEMORY =2,// 共享内存错误返回
LX_INVALID_SIZE =3// 共享内存大小错误
}LX_RETURN_VALUE;
然后,是函数声明:
// 创建共享内存
LX_RETURN_VALUE CreateSharedMemory(UINT nSize);
// 释放共享内存
LX_RETURN_VALUE ReleaseSharedMemory();
// 得到共享内存大小
LX_RETURN_VALUE GetSharedMemorySize(UINT& nSize);
// 向共享内存写入数据
LX_RETURN_VALUE WriteToSharedMemory(void*pData, UINT nSize);
// 从共享内存读取数据
LX_RETURN_VALUE ReadFromSharedMemory(void*pData, UINT nSize);
LX_RETURN_VALUE CreateSharedMemory(UINT nSize);
// 释放共享内存
LX_RETURN_VALUE ReleaseSharedMemory();
// 得到共享内存大小
LX_RETURN_VALUE GetSharedMemorySize(UINT& nSize);
// 向共享内存写入数据
LX_RETURN_VALUE WriteToSharedMemory(void*pData, UINT nSize);
// 从共享内存读取数据
LX_RETURN_VALUE ReadFromSharedMemory(void*pData, UINT nSize);
下面是函数的实现:
// 自动Lock和Unlock互斥量
struct CAutoMutex
{
CAutoMutex();
~CAutoMutex();
// 互斥量
static CMutex m_mutex;
};
CMutex CAutoMutex::m_mutex(FALSE, "StarLeeMutex");
CAutoMutex::CAutoMutex()
{
m_mutex.Lock();
}
CAutoMutex::~CAutoMutex()
{
m_mutex.Unlock();
}
LX_RETURN_VALUE CreateSharedMemory(UINT nSize)
{
// 创建共享内存块
HANDLE hFileMapping = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE,0, nSize, "StarLeeSharedMemory");
// 创建错误
if ((hFileMapping== NULL)|| (hFileMapping== INVALID_HANDLE_VALUE))
return LX_INVALID_SHAREDMEMORY;
// 共享内存已经存在
if (GetLastError()== ERROR_ALREADY_EXISTS)
return LX_SHAREDMEMORY_EXISTS;
// 创建另外一块内存存放共享内存的大小
HANDLE hSize = CreateFileMapping(NULL, NULL, PAGE_READWRITE,0,sizeof(UINT),"StarLeeSharedMemorySize");
if ((hSize == NULL) || (hSize== INVALID_HANDLE_VALUE)|| (GetLastError()== ERROR_ALREADY_EXISTS))
return LX_INVALID_SHAREDMEMORY;
// 得到存放共享内存大小的指针
UINT *pSize= (UINT*)MapViewOfFile(hSize, FILE_MAP_WRITE,0,0,sizeof(UINT));
if (pSize == NULL)
return LX_INVALID_SHAREDMEMORY;
// 写入共享内存的大小
memcpy(pSize, &nSize,sizeof(UINT));
UnmapViewOfFile(pSize);
return LX_OK;
}
LX_RETURN_VALUE ReleaseSharedMemory()
{
CAutoMutex MutexLock;
// 打开共享内存
HANDLE hFileMapping = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE,"StarLeeSharedMemory");
// 关闭共享内存
if (hFileMapping!= NULL)
CloseHandle(hFileMapping);
// 打开存放共享内存大小的文件映射
HANDLE hSize = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE,"StarLeeSharedMemorySize");
// 关闭存放共享内存大小的文件映射
if (hSize!= NULL)
CloseHandle(hSize);
return LX_OK;
}
LX_RETURN_VALUE GetSharedMemorySize(UINT& nSize)
{
CAutoMutex MutexLock;
HANDLE hSize = OpenFileMapping(FILE_MAP_READ, FALSE,"StarLeeSharedMemorySize");
if (hSize == NULL)
return LX_INVALID_SHAREDMEMORY;
UINT *pSize= (UINT*)MapViewOfFile(hSize, FILE_MAP_READ,0,0,sizeof(UINT));
if (pSize == NULL)
return LX_INVALID_SHAREDMEMORY;
// 得到共享内存的大小
memcpy(&nSize, pSize,sizeof(UINT));
return LX_OK;
}
LX_RETURN_VALUE WriteToSharedMemory(void*pDate, UINT nSize)
{
UINT nSharedMemorySize =0;
// 得到共享内存的大小
if (GetSharedMemorySize(nSharedMemorySize)!= LX_OK)
return LX_INVALID_SHAREDMEMORY;
// 检查共享内存的大小
if (nSize> nSharedMemorySize)
return LX_INVALID_SIZE;
CAutoMutex MutexLock;
HANDLE hFileMapping = OpenFileMapping(FILE_MAP_WRITE, FALSE,"StarLeeSharedMemory");
if (hFileMapping== NULL)
return LX_INVALID_SHAREDMEMORY;
void *pMapView = MapViewOfFile(hFileMapping, FILE_MAP_WRITE,0,0, nSize);
if (pMapView== NULL)
return LX_INVALID_SHAREDMEMORY;
// 清空共享内存
memset(pMapView, 0, nSharedMemorySize);
// 将数据写入共享内存
memcpy(pMapView, pDate, nSize);
UnmapViewOfFile(pMapView);
return LX_OK;
}
LX_RETURN_VALUE ReadFromSharedMemory(void*pData, UINT nSize)
{
UINT nSharedMemorySize =0;
if (GetSharedMemorySize(nSharedMemorySize)!= LX_OK)
return LX_INVALID_SHAREDMEMORY;
if (nSize > nSharedMemorySize)
return LX_INVALID_SIZE;
CAutoMutex MutexLock;
HANDLE hFileMapping = OpenFileMapping(FILE_MAP_READ, FALSE,"StarLeeSharedMemory");
if (hFileMapping== NULL)
return LX_INVALID_SHAREDMEMORY;
void *pMapView = MapViewOfFile(hFileMapping, FILE_MAP_READ,0,0, nSize);
if (pMapView== NULL)
return LX_INVALID_SHAREDMEMORY;
// 从共享内存读取数据
memcpy(pData, pMapView, nSize);
UnmapViewOfFile(pMapView);
return LX_OK;
}
struct CAutoMutex
{
CAutoMutex();
~CAutoMutex();
// 互斥量
static CMutex m_mutex;
};
CMutex CAutoMutex::m_mutex(FALSE, "StarLeeMutex");
CAutoMutex::CAutoMutex()
{
m_mutex.Lock();
}
CAutoMutex::~CAutoMutex()
{
m_mutex.Unlock();
}
LX_RETURN_VALUE CreateSharedMemory(UINT nSize)
{
// 创建共享内存块
HANDLE hFileMapping = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE,0, nSize, "StarLeeSharedMemory");
// 创建错误
if ((hFileMapping== NULL)|| (hFileMapping== INVALID_HANDLE_VALUE))
return LX_INVALID_SHAREDMEMORY;
// 共享内存已经存在
if (GetLastError()== ERROR_ALREADY_EXISTS)
return LX_SHAREDMEMORY_EXISTS;
// 创建另外一块内存存放共享内存的大小
HANDLE hSize = CreateFileMapping(NULL, NULL, PAGE_READWRITE,0,sizeof(UINT),"StarLeeSharedMemorySize");
if ((hSize == NULL) || (hSize== INVALID_HANDLE_VALUE)|| (GetLastError()== ERROR_ALREADY_EXISTS))
return LX_INVALID_SHAREDMEMORY;
// 得到存放共享内存大小的指针
UINT *pSize= (UINT*)MapViewOfFile(hSize, FILE_MAP_WRITE,0,0,sizeof(UINT));
if (pSize == NULL)
return LX_INVALID_SHAREDMEMORY;
// 写入共享内存的大小
memcpy(pSize, &nSize,sizeof(UINT));
UnmapViewOfFile(pSize);
return LX_OK;
}
LX_RETURN_VALUE ReleaseSharedMemory()
{
CAutoMutex MutexLock;
// 打开共享内存
HANDLE hFileMapping = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE,"StarLeeSharedMemory");
// 关闭共享内存
if (hFileMapping!= NULL)
CloseHandle(hFileMapping);
// 打开存放共享内存大小的文件映射
HANDLE hSize = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE,"StarLeeSharedMemorySize");
// 关闭存放共享内存大小的文件映射
if (hSize!= NULL)
CloseHandle(hSize);
return LX_OK;
}
LX_RETURN_VALUE GetSharedMemorySize(UINT& nSize)
{
CAutoMutex MutexLock;
HANDLE hSize = OpenFileMapping(FILE_MAP_READ, FALSE,"StarLeeSharedMemorySize");
if (hSize == NULL)
return LX_INVALID_SHAREDMEMORY;
UINT *pSize= (UINT*)MapViewOfFile(hSize, FILE_MAP_READ,0,0,sizeof(UINT));
if (pSize == NULL)
return LX_INVALID_SHAREDMEMORY;
// 得到共享内存的大小
memcpy(&nSize, pSize,sizeof(UINT));
return LX_OK;
}
LX_RETURN_VALUE WriteToSharedMemory(void*pDate, UINT nSize)
{
UINT nSharedMemorySize =0;
// 得到共享内存的大小
if (GetSharedMemorySize(nSharedMemorySize)!= LX_OK)
return LX_INVALID_SHAREDMEMORY;
// 检查共享内存的大小
if (nSize> nSharedMemorySize)
return LX_INVALID_SIZE;
CAutoMutex MutexLock;
HANDLE hFileMapping = OpenFileMapping(FILE_MAP_WRITE, FALSE,"StarLeeSharedMemory");
if (hFileMapping== NULL)
return LX_INVALID_SHAREDMEMORY;
void *pMapView = MapViewOfFile(hFileMapping, FILE_MAP_WRITE,0,0, nSize);
if (pMapView== NULL)
return LX_INVALID_SHAREDMEMORY;
// 清空共享内存
memset(pMapView, 0, nSharedMemorySize);
// 将数据写入共享内存
memcpy(pMapView, pDate, nSize);
UnmapViewOfFile(pMapView);
return LX_OK;
}
LX_RETURN_VALUE ReadFromSharedMemory(void*pData, UINT nSize)
{
UINT nSharedMemorySize =0;
if (GetSharedMemorySize(nSharedMemorySize)!= LX_OK)
return LX_INVALID_SHAREDMEMORY;
if (nSize > nSharedMemorySize)
return LX_INVALID_SIZE;
CAutoMutex MutexLock;
HANDLE hFileMapping = OpenFileMapping(FILE_MAP_READ, FALSE,"StarLeeSharedMemory");
if (hFileMapping== NULL)
return LX_INVALID_SHAREDMEMORY;
void *pMapView = MapViewOfFile(hFileMapping, FILE_MAP_READ,0,0, nSize);
if (pMapView== NULL)
return LX_INVALID_SHAREDMEMORY;
// 从共享内存读取数据
memcpy(pData, pMapView, nSize);
UnmapViewOfFile(pMapView);
return LX_OK;
}
对于代码中能自动锁定和结锁互斥量的结构AutoMutex,可以参考我的《巧用构造函数与析构函数对数据进行设置和恢复》。
用内存映射文件在进程中共享数据
http://blog.csdn.net/zicheng_lin/article/details/6660404
代码如下,具体解释在代码注释中已经说明
程序1:
- // 内存映射文件.cpp : 定义控制台应用程序的入口点。
- //
- #include "stdafx.h"
- #include <Windows.h>
- #include <iostream>
- #include <string>
- using namespace std;
- DWORD WINAPI FirstThread(PVOID pvParam);
- int _tmain(int argc, _TCHAR* argv[])
- {
- string str;
- //从页交换文件中挑拨物理存储器
- static HANDLE hFilemap = CreateFileMapping(INVALID_HANDLE_VALUE,NULL,PAGE_READWRITE,0,4*1024,_T("Shared"));
- //将文件的数据映射到进程的地址空间
- char * pView = (char *)MapViewOfFile(hFilemap,FILE_MAP_READ|FILE_MAP_WRITE,0,0,0);
- if(cin>>str)
- {
- strcpy(pView, (const_cast<char*> (str.c_str())));//赋值
- for(int i=0; i<strlen(pView); ++i)//输出
- {
- cout<<pView[i];
- }
- }
- else
- {
- cout<<*pView<<endl;
- }
- system("pause");
- return 0;
- }
// 内存映射文件.cpp : 定义控制台应用程序的入口点。//#include "stdafx.h"#include <Windows.h>#include <iostream>#include <string>using namespace std;DWORD WINAPI FirstThread(PVOID pvParam);int _tmain(int argc, _TCHAR* argv[]){string str; //从页交换文件中挑拨物理存储器static HANDLE hFilemap = CreateFileMapping(INVALID_HANDLE_VALUE,NULL,PAGE_READWRITE,0,4*1024,_T("Shared"));//将文件的数据映射到进程的地址空间char * pView = (char *)MapViewOfFile(hFilemap,FILE_MAP_READ|FILE_MAP_WRITE,0,0,0);if(cin>>str){strcpy(pView, (const_cast<char*> (str.c_str()))); //赋值for(int i=0; i<strlen(pView); ++i) //输出{cout<<pView[i];}}else{cout<<*pView<<endl;}system("pause");return 0;}
程序2:
- // 内存映射文件.cpp : 定义控制台应用程序的入口点。
- //
- #include "stdafx.h"
- #include <Windows.h>
- #include <iostream>
- #include <string>
- using namespace std;
- DWORD WINAPI FirstThread(PVOID pvParam);
- int _tmain(int argc, _TCHAR* argv[])
- {
- HANDLE hFilemap1 = OpenFileMapping(FILE_MAP_READ|FILE_MAP_WRITE,FALSE,_T("Shared"));//打开名为 Shared的映射对象.
- if(hFilemap1 == NULL)
- {
- cout<<"openfilemapping 失败"<<endl;
- }
- char *pView = (char*)MapViewOfFile(hFilemap1,FILE_MAP_READ|FILE_MAP_WRITE,0,0,0);
- if(pView == NULL)
- {
- cout<<"map view 失败"<<endl;
- }
- else
- {
- for(int i=0; i<strlen(pView); ++i)
- {
- cout<<pView[i];
- }
- UnmapViewOfFile(pView);
- }
- CloseHandle(hFilemap1);
- system("pause");
- return 0;
- }
// 内存映射文件.cpp : 定义控制台应用程序的入口点。//#include "stdafx.h"#include <Windows.h>#include <iostream>#include <string>using namespace std;DWORD WINAPI FirstThread(PVOID pvParam);int _tmain(int argc, _TCHAR* argv[]){HANDLE hFilemap1 = OpenFileMapping(FILE_MAP_READ|FILE_MAP_WRITE,FALSE,_T("Shared")); //打开名为 Shared的映射对象.if(hFilemap1 == NULL){cout<<"openfilemapping 失败"<<endl;}char *pView = (char*)MapViewOfFile(hFilemap1,FILE_MAP_READ|FILE_MAP_WRITE,0,0,0);if(pView == NULL){cout<<"map view 失败"<<endl;}else{for(int i=0; i<strlen(pView); ++i){cout<<pView[i];}UnmapViewOfFile(pView);}CloseHandle(hFilemap1);system("pause");return 0;}
程序2共享程序1中创建的内容.
- 用内存映射文件在进程中共享数据
- 用内存映射文件在进程中共享数据
- 利用内存映射文件在两个进程间共享数据
- 使用内存映射文件在进程之间共享数据
- 利用内存映射文件在进程间共享数据
- 使用内存映射文件在进程之间共享数据
- 利用内存映射文件在进程间共享数据
- 使用内存映射文件在进程间共享数据
- 使用内存映射文件在进程间共享数据
- 用内存映射文件在进程中共享数据http://blog.csdn.net/zicheng_lin/article/details/6660404
- windows笔记-使用内存映射文件在进程之间共享数据
- Win32汇编使用内存映射文件在进程间共享数据
- 通过内存映射文件实现进程间数据共享
- c++ 内存映射文件进程间共享数据
- 内存映射文件进程间共享内存
- 内存映射文件进程间共享内存
- 用内存映射在多个应用程序之间共享数据
- 数据共享,内存映射文件和虚拟内存,共享内存
- jsp标签jsp:setProperty用法
- 19 使用缓冲区是否一定可以提高复制效率
- android中如何模拟QQ登录状态
- hdu 4312 Meeting point-2
- jBPM4的PVM解析
- 用内存映射文件在进程中共享数据
- 让数据库飞起来 10大DB2优化技巧
- 优化SQL Server数据库查询方法
- 如何在程序运行中动态改变对象属性在PropertyGrid可见性和只读属性
- 属性串行化
- Peas Malaysian show goes ahead 黑眼豆豆乐队马来西
- Yii源码分析——CComponent
- 《编程之道》
- 值得关注的三个开源的云计算项目