最近学习一下共享内存,从别的地方转过来的代码,记录一下,这份代码分三个工程,ShareMemory(共享内存类库,已封装成DLL),Client(测试客户端进程), Server(测试服务端进程),不多说,直接上代码:
ShareMemory.h文件:
// ShareMemory.h: interface for the CShareMemory class.
//
//
#if !defined(AFX_SHAREMEMORY_H__0B0797DE_D3D1_4CCC_976B_44F87546607A__INCLUDED_)
#define AFX_SHAREMEMORY_H__0B0797DE_D3D1_4CCC_976B_44F87546607A__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#ifdef SHAREMEMORY_EXPORTS
#define SHAREMEMORY_EXPORT __declspec(dllexport)
#else
#define SHAREMEMORY_EXPORT __declspec(dllimport)
#endif
#include <windows.h>
class SHAREMEMORY_EXPORT CShareMemory
{
public:
VOID Unlock();
BOOL IsLocked();
LPVOID Lock(DWORD dwWaitTimeout=INFINITE);
BOOL IsValid();
DWORD GetBytes();
VOID Close();
BOOL Open(LPCTSTR szName);
BOOL Create(LPCTSTR szName, DWORD dwBytes);
CShareMemory();
virtual ~CShareMemory();
protected:
DWORD m_dwBytes;
HANDLE m_hFileMap;
BOOL m_bLocked;
LPVOID m_pData;
HANDLE m_hFile;
HANDLE m_hMutex;
};
#endif // !defined(AFX_SHAREMEMORY_H__0B0797DE_D3D1_4CCC_976B_44F87546607A__INCLUDED_)
ShareMemory.cpp文件:
// ShareMemory.cpp: implementation of the CShareMemory class.
//
//
#include "ShareMemory.h"
#include <stdio.h>
//
// Construction/Destruction
//
CShareMemory::CShareMemory()
{
m_hFile=INVALID_HANDLE_VALUE;
m_hMutex=NULL;
m_pData=NULL;
m_hFileMap=NULL;
m_dwBytes=0;
}
CShareMemory::~CShareMemory()
{
Close();
}
BOOL CShareMemory::Create(LPCTSTR szName, DWORD dwBytes)
{
BOOL T=FALSE;
char szBuf[MAX_PATH];
LPCTSTR szFile;
if(szName!=NULL&&dwBytes>0)
{
Close();
szFile=tmpnam(szBuf);
if(szFile!=NULL)
{
m_hFile=CreateFile(szFile, GENERIC_WRITE|GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_TEMPORARY|FILE_FLAG_DELETE_ON_CLOSE, NULL);
if(m_hFile!=INVALID_HANDLE_VALUE)
{
if(SetFilePointer(m_hFile, dwBytes+sizeof(DWORD), NULL, FILE_BEGIN)!=-1)
{
if(SetEndOfFile(m_hFile))
{
m_hFileMap=CreateFileMapping(m_hFile, NULL, PAGE_READWRITE, 0, dwBytes+sizeof(DWORD), szName);
if(m_hFileMap!=NULL)
{
m_dwBytes=dwBytes;
m_pData=MapViewOfFile(m_hFileMap, FILE_MAP_ALL_ACCESS, 0, 0, sizeof(DWORD)+dwBytes);
if(m_pData!=NULL)
{
*((LPDWORD)m_pData)=dwBytes;
sprintf(szBuf, "Mutex<%s>", szName);
m_hMutex=CreateMutex(NULL, FALSE, szBuf);
if(m_hMutex!=NULL)
{
if(GetLastError()!=ERROR_ALREADY_EXISTS)
{
T=TRUE;
}
}
}
}
}
}
}
if(!T)
{
Close();
}
}
}
return T;
}
BOOL CShareMemory::Open(LPCTSTR szName)
{
BOOL T=FALSE;
char szBuf[MAX_PATH];
if(szName!=NULL)
{
Close();
m_hFileMap=OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, szName);
if(m_hFileMap!=NULL)
{
sprintf(szBuf, "Mutex<%s>", szName);
m_hMutex=OpenMutex(MUTEX_ALL_ACCESS, FALSE, szBuf);
if(m_hMutex!=NULL)
{
m_pData=MapViewOfFile(m_hFileMap, FILE_MAP_ALL_ACCESS, 0, 0, m_dwBytes+sizeof(DWORD));
if(Lock())
{
m_dwBytes=*((LPDWORD)m_pData);
Unlock();
if(m_dwBytes>0)
{
T=TRUE;
}
}
}
}
if(!T)
{
Close();
}
}
return T;
}
VOID CShareMemory::Close()
{
if(m_bLocked)
{
Unlock();
}
if(m_pData!=NULL)
{
UnmapViewOfFile(m_pData);
m_pData=NULL;
}
if(m_hFileMap!=NULL)
{
CloseHandle(m_hFileMap);
m_hFileMap=NULL;
}
if(m_hFile!=INVALID_HANDLE_VALUE)
{
CloseHandle(m_hFile);
m_hFile=INVALID_HANDLE_VALUE;
}
if(m_hMutex!=NULL)
{
CloseHandle(m_hMutex);
m_hMutex=NULL;
}
m_dwBytes=0;
}
DWORD CShareMemory::GetBytes()
{
return m_dwBytes;
}
BOOL CShareMemory::IsValid()
{
return (m_hFileMap!=NULL&&m_hMutex!=NULL);
}
LPVOID CShareMemory::Lock(DWORD dwWaitTimeout)
{
LPVOID pData=NULL;
if(IsValid()&&m_pData!=NULL&&!m_bLocked)
{
if(WaitForSingleObject(m_hMutex, dwWaitTimeout)!=WAIT_TIMEOUT)
{
m_bLocked=TRUE;
}
if(m_bLocked)
{
pData=(LPVOID)((LPDWORD)m_pData+1);
}
}
return pData;
}
BOOL CShareMemory::IsLocked()
{
return m_bLocked;
}
VOID CShareMemory::Unlock()
{
if(m_bLocked)
{
ReleaseMutex(m_hMutex);
m_bLocked=FALSE;
}
}
Server.cpp: 为了增加可读性,加了一些注释说明。
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
#include <iostream>
#include "ShareMemory.h"
#pragma comment(lib, "ShareMemory.lib")
void main()
{
//共享内存对象
CShareMemory sm;
char ch;
//创建共享内存
if(sm.Create("Server", 1024))
{
LPSTR szMessage;
printf("Share memory created!\n");
//Lock后则可以写入数据了
szMessage=(LPSTR)sm.Lock(100);
//获取到的szMessage数据指针指向共享内存,任何时候都可以取到里面的数据,
//szMessage数据在多线程中应用是否正常,还待验证
if(szMessage)
{
//sprintf(szMessage, "Hellodsafmasdlkjfsda,mnf,dmsaf!");
ch=szMessage[0];
sm.Unlock();
printf("Message has been delivered!\n");
//while (true)
//{
// char szInput[1024] = { 0 };
// std::cin >> szInput;
// szMessage = (LPSTR)sm.Lock(1);
// sprintf(szMessage, "%s", szInput);
// sm.Unlock();
//}
while (!kbhit())
{
if (szMessage != NULL)
{
if (szMessage[0] != ch)
{
ch = szMessage[0];
//putchar(ch);
printf("%s\n", szMessage);
}
}
}
}
else
{
printf("Lock memory failed!\n");
getch();
}
sm.Close();
}
}
Client:
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
#include "ShareMemory.h"
#pragma comment(lib, "ShareMemory.lib")
void main()
{
CShareMemory sm;
if(sm.Open("Server"))
{
LPSTR szMessage;
int ch;
printf("Share memory opened! It's %d bytes.\n", sm.GetBytes());
//客户端所取到的szMessage指针指向服务端进程申请的共享内存,
//任何一方对这块内存操作,效果都是一样的。
szMessage=(LPSTR)sm.Lock(300);
if(szMessage!=NULL)
{
sm.Unlock();
printf("Server message is: %s\n", szMessage);
while(1)
{
ch=getch();
if(ch==0x1b)
{
break;
}
putchar(ch);
szMessage=(LPSTR)sm.Lock();
if(szMessage!=NULL)
{
szMessage[0]=(char)ch;
sm.Unlock();
}
printf("%s\n", szMessage);
}
}
else
{
printf("Lock memory failed!\n");
getch();
}
sm.Close();
}
}
运行效果如下图: