MFC 进程之间通讯之内存映射文件
内存映射文件,是由一个文件到一块内存的映射。Win32提供了允许应用程序把文件映射到一个进程的函数 (CreateFileMapping)。内存映射文件与虚拟内存有些类似,通过内存映射文件可以保留一个地址空间的区域,同时将物理存储器提交给此区域,内存文件映射的物理存储器来自一个已经存在于磁盘上的文件,而且在对该文件进行操作之前必须首先对文件进行映射。使用内存映射文件处理存储于磁盘上的文件时,将不必再对文件执行I/O操作,使得内存映射文件在处理大数据量的文件时能起到相当重要的作用。
代码操作:
新建一个基于对话框的MFC工程,名字为:ShareMemoryTest
在该工程添加一个类:CShareMemory便于以后可以重用
ShareMemory.h:
#pragma once class CShareMemory { HANDLE m_hFileHandle; HANDLE m_hFileMapHanlde; char * m_pMapOfFile; public: CShareMemory(void); ~CShareMemory(void); char * Create(CString strFileName, DWORD dwFileSize); BOOL Delete(); char * Open(CString strFileName); };
ShareMemory.cpp
#include "StdAfx.h" #include "ShareMemory.h" CShareMemory::CShareMemory(void) { m_hFileHandle = NULL; m_hFileMapHanlde = NULL; m_pMapOfFile = NULL; } CShareMemory::~CShareMemory(void) { Delete(); } /* Function: create map file and return point to operation Param: strFileName[in]: local harddisk file name dwFileSize[in]: file map size return: char*: the point to read/write file */ char* CShareMemory::Create(CString strFileName, DWORD dwFileSize) { m_hFileHandle = ::CreateFile(strFileName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if(NULL == m_hFileHandle) { return NULL; } m_hFileMapHanlde = ::CreateFileMapping(m_hFileHandle, NULL, PAGE_READWRITE, 0, dwFileSize, strFileName); if(NULL == m_hFileMapHanlde) { int errNo = GetLastError(); ::CloseHandle(m_hFileHandle); return NULL; } char * pMapOfFile = (char *)::MapViewOfFile(m_hFileMapHanlde, FILE_MAP_ALL_ACCESS, 0, 0, 0); //the entire file is mapped. if(NULL == pMapOfFile) { ::CloseHandle(m_hFileMapHanlde); return NULL; } m_pMapOfFile = pMapOfFile; memset(m_pMapOfFile, 0, dwFileSize); return pMapOfFile; } /* Function: delete handle and release memory Param: NULL return: TRUE: delete success FALSE: delete failed */ BOOL CShareMemory::Delete() { if(NULL != m_hFileHandle) { if(!::CloseHandle(m_hFileHandle)) { return FALSE; } } if(NULL != m_hFileMapHanlde) { if(!::CloseHandle(m_hFileMapHanlde)) { return FALSE; } } if(NULL != m_pMapOfFile) { if(!::UnmapViewOfFile(m_pMapOfFile)) { return FALSE; } } return TRUE; } /* Function: open a exist file mapping Param: strFileName: is need to same to Create return: char*: the point to read/write file */ char* CShareMemory::Open(CString strFileName) //strFileName is need to equal to Create { HANDLE hExistFileMapHandle = ::OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, strFileName); if(NULL == hExistFileMapHandle) { return NULL; } char * pMapOfFile = (char *)::MapViewOfFile(hExistFileMapHandle, FILE_MAP_ALL_ACCESS, 0, 0, 0); //the entire file is mapped. if(NULL == pMapOfFile) { ::CloseHandle(m_hFileMapHanlde); return NULL; } m_pMapOfFile = pMapOfFile; return pMapOfFile; }
在ShareMemoryTestDlg.cpp中,【ok】按钮的响应函数,添加如下代码:
void CShareMemoryTestDlg::OnBnClickedOk() { // TODO: Add your control notification handler code here //CDialogEx::OnOK(); CString strShareMemory = "hello my first mapping file!\n"; CShareMemory ShareMemory; char *pShareMemory = ShareMemory.Create("D:\ShareMemoryTestFile.txt", strShareMemory.GetLength()); if(pShareMemory) { sprintf(pShareMemory, strShareMemory); AfxMessageBox("write over"); } }
以上第一个进程的写操作执行完毕,下面再创建另一个基于对话框的MFC的工程,名字为:ShareMemoryTest2
同样在ShareMemoryTestDlg.cpp中,【ok】按钮的响应函数,添加如下代码:
void CShareMemoryTest2Dlg::OnBnClickedOk() { // TODO: Add your control notification handler code here //CDialogEx::OnOK(); CShareMemory ShareMemory; char *pShareMemory = ShareMemory.Open("D:\ShareMemoryTestFile.txt"); if(pShareMemory) { AfxMessageBox(pShareMemory); } }
这样让进程1一直执行,进程2后运行,这样进行2就可以显示进程1所写入的数据
注意:不要点掉进程1的弹出对话框,否则就会进入析构,删除共享内存