Windows共享数据和信息的机制:RPC、COM、OLE、DDE、窗口消息、剪贴板、邮箱、管道、套接字以及内存映射文件。
内存映射:通过让两个或多个进程映射同一个文件。(在进程空间中保留一个地址空间区域,将物理存储器提交给该区域)
内存映射文件的物理存储器(用来作为虚拟内存)来自一个位于磁盘驱动器上的数据文件。一旦该文件被映射,就可以访问它,就像文件已经加载内存一样。(操作系统使得内存能够将一个数据文件映射到进程的地址空间中)
CreateFile //创建或打开文件内核对象
CreateFileMapping //创建文件映射内核对象(OpenFileMapping,在其它进程中,打开文件映射对象)
MapViewOfFile //将文件数据映射到进程的地址空间
UnmapViewOfFile //从进程的地址空间撤销文件数据的映像
CloseHandle //关闭文件对象和文件映射对象
同时为了方便进程间数据共享,Microsoft提供了基于页文件的内存映射文件
与创建内存映射磁盘文件基本相同,但是不必调用CreateFile,因为不是创建或打开指定的文件。只需要像通常那样调用CreateFileMapping函数:
HANDLE WINAPI CreateFileMapping(
HANDLE hFile,
LPSECURITY_ATTRIBUTESlpAttributes,
DWORD lProtect,
DWORD dwMaximumSizeHigh,
DWORD dwMaximumSizeLow,
LPCTSTR lpName
);
传递INVALID_HANDLE_VALUE作为hFile的参数,这是告诉系统:这不是创建驻留在磁盘上的文件的映射对象,而是从系统的页文件中提交物理存储器。
且分配的存储器的大小由dwMaximumSizeHigh和dwMaximumSizeLow两个函数来决定。
共享内存的写入端程序(同时创建了带原子操作的线程来观察内存间Interlocked系列的原子操作是否有效)
#include
#include
#include
using namespace std;
#ifdef _UNICODE
#define tstring wstring
#else
#define tstring string
#endif
UINT _stdcall writeFunc(void *pvContext)
{
//InterlockedIncrement((long*)pvContext);
InterlockedExchangeAdd((long*)pvContext, 1);
return 0;
}
int _tmain(int argc, _TCHAR* argv[])
{
tstring mapName = _T("sharememory");//多进程想指向同一内存块,共享内存名称必须相同
INT *pCount = NULL;
HANDLE threadHandle;
HANDLE hMapMem;
hMapMem = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 4, mapName.c_str());
if (hMapMem == NULL)
{
printf("创建共享内存失败\n");
}
else
{
pCount = (INT*)MapViewOfFile(hMapMem, FILE_MAP_ALL_ACCESS, 0, 0, 0);
*pCount = 0;
//先开启共享写入进程
//如果想观察线程间互斥效果,请在此时打开读取进程,然后在继续
getchar();
for (INT index = 0; index < 1000; index++)
{
threadHandle = (HANDLE)_beginthreadex(NULL, 0, writeFunc, (void*)pCount, 0, NULL);
if (threadHandle)
{
WaitForSingleObject(threadHandle, INFINITE);
printf("写入共享文件内存%d\n", *pCount);
CloseHandle(threadHandle);
}
}
fflush(stdin);//刷新标准输入流
getchar();
printf("写入共享文件内存%d\n", *pCount);
UnmapViewOfFile(pCount);
CloseHandle(hMapMem);
}
system("pause");
return 0;
}
共享内存的读取端程序
#include
#include
#include
using namespace std;
#ifdef _UNICODE
#define tstring wstring
#else
#define tstring string
#endif
UINT _stdcall readFunc(void *pvContext)
{
//InterlockedDecrement((long*)pvContext);
InterlockedExchangeAdd((long*)pvContext, -1);
return 0;
}
int _tmain(int argc, _TCHAR* argv[])
{
tstring mapName = _T("sharememory");
INT *pCount = NULL;
HANDLE threadHandle;
HANDLE hMapMem;
hMapMem = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, mapName.c_str());
if (hMapMem == NULL)
{
printf("打开共享内存失败\n");
}
else
{
pCount = (INT*)MapViewOfFile(hMapMem, FILE_MAP_ALL_ACCESS, 0, 0, 0);
while ((*pCount) == 0)
{
Sleep(0);//放弃当前CPU时间片
}
for (INT index = 0; index < 1000; index++)
{
threadHandle = (HANDLE)_beginthreadex(NULL, 0, readFunc, (void*)pCount, 0, NULL);
if (threadHandle)
{
WaitForSingleObject(threadHandle, INFINITE);
printf("读取共享文件内存%d\n", *pCount);
CloseHandle(threadHandle);
}
}
getchar();
printf("读取共享文件内存%d\n", *pCount);
UnmapViewOfFile(pCount);
CloseHandle(hMapMem);
}
system("pause");
return 0;
}
Windows共享内存示例 http://www.cnblogs.com/dongsheng/p/4460944.html