进程间通信的方式有很多种,其底层原理使用的都是内存映射文件。
本文实现了Windows核心编程第五版475页上的demo,即使用内存映射文件来在进程间通信。
进程1
按钮【Create mapping of Data】用来创建命名内存映射文件,后备存储器为页交换文件,而非磁盘上的文件,大小为4K,将全部大小映射到进程地址空间,将Data中的数据写入该内存映射文件,然后撤销对文件视图的映射。注意在进程1里不能CloseHandle(m_hFileMapping)
进程2
按钮【Open maping and get Data】用来打开进程1创建的命名内存映射文件,将全部大小映射到进程地址空间,从中读出数据,将数据内容放到Data里。
按钮【Close mapping of Data】用来关闭CloseHandle进程1返回的内存映射文件m_hFileMapping。
1 void CMemoryMappingDlg::OnBnClickedBtnCreate2() 2 { 3 // TODO: 在此添加控件通知处理程序代码;
4 LPCTSTR lpFileMappingName = _T("MMFSharedData"); 5 m_hFileMapping = CreateFileMapping( 6 INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 4 * 1024, lpFileMappingName); 7 DWORD dwErr = GetLastError(); 8
9 if (NULL == m_hFileMapping ) 10 { 11 AfxMessageBox(_T("无法创建该内存映射文件")); 12 return; 13 } 14 if (dwErr == ERROR_ALREADY_EXISTS) 15 { 16 AfxMessageBox(_T("存在同名内存映射文件")); 17 CloseHandle(m_hFileMapping); 18 return; 19 } 20
21 PVOID pMapOfView = MapViewOfFile(m_hFileMapping, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0 /*4 * 1024*/); 22 if (NULL == pMapOfView) 23 { 24 AfxMessageBox(_T("映射该文件错误")); 25 CloseHandle(m_hFileMapping); 26 return; 27 } 28
29 ZeroMemory(pMapOfView, 4 * 1024); 30
31 CString strText; 32 GetDlgItemText(IDC_EDIT_DATA, strText); 33 memcpy_s(pMapOfView, (strText.GetLength() + 1) * sizeof(TCHAR), strText.GetBuffer(), 34 (strText.GetLength() + 1) * sizeof(TCHAR)); 35
36 UnmapViewOfFile(pMapOfView); 37 //CloseHandle(m_hFileMapping); 不能执行此句,否则进程2不能打开该命名内存映射文件。
38 } 39
40 void CMemoryMappingDlg::OnBnClickedBtnClose() 41 { 42 // TODO: 在此添加控件通知处理程序代码;
43 CloseHandle(m_hFileMapping); 44 } 45
46 void CMemoryMappingDlg::OnBnClickedBtnOpen() 47 { 48 // TODO: 在此添加控件通知处理程序代码
49 LPCTSTR lpFileMappingName = _T("MMFSharedData"); 50
51 //OpenFileMapping的第一个参数一定不能是PAGE_**, 区别于CreateFileMapping函数 52 //HANDLE hFileMapping = OpenFileMapping(PAGE_READWRITE, FALSE, lpFileMappingName);
53 HANDLE hFileMapping = OpenFileMapping(FILE_MAP_READ | FILE_MAP_WRITE, FALSE, lpFileMappingName); 54
55 if (NULL == hFileMapping) 56 { 57 AfxMessageBox(_T("打不开该内存映射文件")); 58 return; 59 } 60
61 PVOID pMapOfFile = MapViewOfFile(hFileMapping, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0 /*4 * 1024 */); 62 if (NULL == pMapOfFile) 63 { 64 AfxMessageBox(_T("映射该文件错误")); 65 CloseHandle(hFileMapping); 66 return; 67 } 68
69 TCHAR tchArr[256]; 70 ZeroMemory(tchArr, sizeof(tchArr)); 71 memcpy_s(tchArr, sizeof(tchArr), pMapOfFile, sizeof(tchArr)); 72 SetDlgItemText(IDC_EDIT_DATA, tchArr); 73
74 UnmapViewOfFile(pMapOfFile); 75 CloseHandle(hFileMapping); 76 }
需要注意的地方是:
0、后备存储器为页交换文件的内存映射文件,CreateFileMapping的文件句柄参数为INVALID_HANDLE_VALUE
1、进程1创建了命名内存映射文件后,一定不能CloseHandle(内存映射文件句柄),否则进程2不能OpenFileMapping打开该命名内存映射文件
2、OpenFileMapping的第一个参数一定不能是PAGE_**, 区别于CreateFileMapping函数