0%

内存映射ShareMemory

共享内存

Windows下进程的地址空间在逻辑上是相互隔离的,但在物理上却是重叠的,就是说一块内存,可以给好多进程用,比若说共享内存进行读取,有点像管道奥。
今天还是照着书写的,可能在写这一张的人没怎么注意,还是有一个错误就是提前进行UnMap了。
我们首先看一下这个共享内存的简单实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <iostream>
#include <windows.h>
#include <stdio.h>
using namespace std;
int main()
{
char szName[] = "MemoryName";
char szData[] = "123456789";
LPVOID pBuffer;
HANDLE hMap = OpenFileMapping(FILE_MAP_ALL_ACCESS,0,szName);
if(hMap != NULL)
{
pBuffer = MapViewOfFile(hMap,FILE_MAP_ALL_ACCESS,0,0,0);
//cout<<pBuffer<<endl;
printf("读出数据%s",pBuffer);
}else
{
hMap = CreateFileMapping(INVALID_HANDLE_VALUE,NULL,PAGE_READWRITE,0,strlen(szData)+1,szName);
pBuffer = MapViewOfFile(hMap,FILE_MAP_ALL_ACCESS,0,0,0);
strcpy((char *)pBuffer,szData);
cout<<"写入数据"<<szData<<endl;
}
getchar();
UnmapViewOfFile(pBuffer);
CloseHandle(hMap);
return 0;
}

首先我们现实定义了一个数据名称和数据值,然后尝试打开这个内存映射,如果打开失败的话呢就是没有创建这个内存映射然后我们就开始创建,现实创建一个内存映射,然后在用MapViewOfFile进行内存地址的分配,然后再用strcpy进行数据的copy,然后就在这个时候,书上写的是吧getchar()卸载CloseHandle后面,但是这个样子就没有意义了,那么我们就应该先让他卡住才行,如果打开这个内存映射成功的话呢我们就读取这个内存映射的地址,然后输出,在这里需要注意不能用C++的一个输入输出流,因为我们定义pBuffer的时候我们不是定义的char类型,而是一个通用的指针类型,这里需要注意。

CShareMemory类的封装

在这里我们封装一下我们的内存共享类,方便之后的使用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#ifndef __SHAREMEMORY_H__
#define __SHAREMEMORY_H__
#include <Windows.h>
class CShareMemory
{
public:
CShareMemory(const char *pszMapName,int nFileSzie = 0,BOOL bSever = FALSE);
~CShareMemory();
LPVOID GetBuffer()const {return m_pBuffer;}
private:
LPVOID m_pBuffer;
HANDLE m_hFileMap;
BOOL m_bSever;
};
inline CShareMemory::CShareMemory(const char *pszMapName,int nFileSzie,BOOL bSever):m_hFileMap(NULL),m_pBuffer(NULL)
{
if (bSever)
{
m_hFileMap = CreateFileMapping(INVALID_HANDLE_VALUE,NULL,PAGE_READWRITE,0,nFileSzie,pszMapName);

}else
{
m_hFileMap = OpenFileMapping(FILE_MAP_ALL_ACCESS,FALSE,pszMapName);
}
m_pBuffer = (LPBYTE)MapViewOfFile(m_hFileMap,FILE_MAP_ALL_ACCESS,0,0,0);
m_bSever = bSever;
}
inline CShareMemory::~CShareMemory()
{
if (m_bSever)
{
UnmapViewOfFile(m_pBuffer);
CloseHandle(m_hFileMap);
}

}

#endif//__SHAREMEMORY_H__

和之前一样还是判断是否是重定义了,然后就是一个服务端几个客户端的类型,这个地方书上写的不是很严谨,我不知道是他没注意还是他就是这个意思,读他的析构函数的时候我发现,他并没有判断这个是不是服务器端还是客户端就进行了映射的关闭,我怀疑他是这个地方有点误解。
在这里写的时候他用了一个内联函数的方法进行写的,析构函数这个可以,但是这个构造函数我感觉其实是没啥必要,都这么多行了,是不是内联的都无所谓了我感觉(内联函数就是编译器直接拷贝,不需要进行函数的构造这种的),然后在函数后面有个const意思就是说,我们这个函数是不会修改这个成员变量的值的,参数有const的话呢就是说我们不会修改这个参数的值的。还有就是函数后面跟上其实就是将后面的变量进行初始化,如果构造函数后面有的话呢一般来说就是父类的一个初始化了,这里比较特殊。