一 进程逻辑空间 物理空间
如上图所示,每个进程都有自己的逻辑空间,这些逻辑空间,会被映射到具体的物理空间中。
每个进程的逻辑空间都是彼此隔离,相互独立不受干扰的。
但是他们都会被映射到同一个物理空间去,当其所映射的物理空间有重叠的时,这重叠的部分就共享了物理内存
二 共享内存关键问题
创建物理内存
将物理内存映射到进程空间
读写互斥控制
1)创建物理内存,获得物理内存资源句柄
比如 由A进程 负责创建共享内存
A: 进程创建完物理内存后,直接返回物理内存句柄
// 创建共享文件句柄 HANDLE hMapFile = CreateFileMapping( INVALID_HANDLE_VALUE, // 物理文件句柄 NULL, // 默认安全级别 PAGE_READWRITE, // 可读可写 0, // 高位文件大小 BUF_SIZE, // 地位文件大小 L"ShareMemory" // 共享内存名称 );
B:B进程通过共享内存的全局名字,来获得共享物理内存句柄
// 打开共享的文件对象 HANDLE hMapFile = OpenFileMapping(FILE_MAP_ALL_ACCESS,NULL,L"ShareMemory");
2) 物理内存映射进程空间
各个进程都是通过这种方式, 将物理空间共享内存,映射到进程逻辑空间
// 映射缓存区视图 , 得到指向共享内存的指针 LPVOID lpBase = MapViewOfFile( hMapFile, // 共享内存的句柄 FILE_MAP_ALL_ACCESS, // 可读写许可 0, 0, BUF_SIZE );
3) 释放
进程退出时,要解除映射
// 解除文件映射
UnmapViewOfFile(lpBase);
// 关闭内存映射文件对象句柄
CloseHandle(hMapFile);
4)互斥控制
采用互斥量或信号的机制
互斥量机制
进程A: 创建互斥量mutex while(1) { 申请mutex; 处理C; 释放mutex; 其他操作; }
进程B: while(1) { 申请mutex; 处理C; 释放mutex; 其他操作; }
示例:
进程A
#include #include using namespace std; int main(){// 若不存在名为"pmutex"的互斥量则创建它;否则获取其句柄 HANDLE hMutex = CreateMutex(NULL, false, "pmutex"); if(NULL == hMutex) { cout<
进程B
#include #include using namespace std; int main(){// 若不存在名为"pmutex"的互斥量则创建它;否则获取其句柄 HANDLE hMutex = CreateMutex(NULL, false, "pmutex"); if(NULL == hMutex) { cout<
信号量机制:
进程A : 执行 写操作
进程A 执行写操作//等待其他进程读操作完毕WaitForSingleObject(m_memMng.m_hReadEvent, INFINITE); //重置写操作信号量ResetEvent(m_memMng.m_hWriteEvent);//执行写操作memcpy//写操作完毕,恢复信号量,使得其它进程可读SetEvent(m_memMng.m_hWriteEvent);
进程B: 执行读操作
//进程B执行读操作//等待主进程写完毕WaitForSingleObject(m_memMng.m_hWriteEvent, INFINITE);//重置读信号量ResetEvent(m_memMng.m_hReadEvent);//读操作,将共享内存数据拷贝本地变量memcpy//读操作完毕,设置信号量信号SetEvent(m_memMng.m_hReadEvent);
三 封装
应该有的成员变量:
1)创建物理内存、映射进程空间 管理
HANDLE hMapping_; 物理空间资源句柄
MappedView View_; 物理映射成进程空间的操作
int size_; 物理空间大小
std::wstring name_; 共享内存名字
2) 信号量控制管理
HANDLE m_hReadEvent;
HANDLE m_hWriteEvent;
操作方法:
1)创建
bool CreateFileMap(); //创建
bool OpenFileMap(); //已存在,则打开
bool MapView(bool bCanWrite = true); //映射进程空间
2)映射管理类
class MappedView{public:MappedView() : view_(NULL) {}~MappedView() { CloseView(); }bool MapView(SharedMemory *shared_memory, bool can_write);//MapViewOfFilevoid CloseView();char *view() { return view_; }private: char *view_=nullptr;};
共享内存管理类
class SharedMemory{public:SharedMemory() : hMapping_(NULL) {size_ = 0;m_hReadEvent = NULL;m_hWriteEvent = NULL;}~SharedMemory() { Close(); if (m_hReadEvent) {CloseHandle(m_hReadEvent); }if (m_hWriteEvent)CloseHandle(m_hWriteEvent);};public://初始化bool InitReceiver(std::wstring name, std::wstring readName = L"ShareMemoryReadEvent