之前自己做的一个项目涉及到进程间通信问题,我采用的是SOCKET方式。面试的时候有问过为什么不采用其他方式。好吧,其实发现共享内存更方便一点。于是自己写了一下,并且做了个测试界面。
程序启动会获得自身的窗口句柄,另外可以输入一个窗口句柄,用于进程间Windows消息通信。File Mapping Name实际上就是内核对象名,进程间依据这个来访问共享内存。
Windows下的共享内存实际是用文件映射实现的,可以用CreateFileMapping创建一个内存文件映射对象,用于映射文件到内存。该函数返回的是File Mapping Object句柄
CreateFileMappingA( __in HANDLE hFile, __in_opt LPSECURITY_ATTRIBUTES lpFileMappingAttributes, __in DWORD flProtect, __in DWORD dwMaximumSizeHigh, __in DWORD dwMaximumSizeLow, __in_opt LPCSTR lpName );
1)因为并不需要创建一个实际的文件,所以把hFile设置成为0xFFFFFFFF(INVALID_HANDLE_VALUE)就行了。
2)Windows支持64位的文件,但一般内存不会超过4G也就是32位文件就够用了,所以上面的参数当中,dwMaximumSizeHigh为0,dwMaximumSizeLow设置为需要开辟的内存大小。
3)lpName用于标示这段内存,进程间通过这个标示访问这段内存。
接着调用MapViewOfFile()映射到当前进程的虚拟地址上。该函数如果调用成功,返回映射文件的开始地址。如果失败为NULL。
MapViewOfFile( __in HANDLE hFileMappingObject, __in DWORD dwDesiredAccess, __in DWORD dwFileOffsetHigh, __in DWORD dwFileOffsetLow, __in SIZE_T dwNumberOfBytesToMap );
1)hFileMappingObject就是刚才调用CreateFileMapping返回的句柄。
2)dwDesiredAccess设置为FILE_MAP_ALL_ACCESS。
3)dwNumberOfBytesToMap,文件中要映射的字节数,也就是这块共享内存的大小。
我的程序是这么调用它的。
int Cp1Dlg::MapFile() { CString str; m_edit7.GetWindowTextA(str); if(str.GetLength() == 0) { AfxMessageBox("File Mapping Name can't be NULL"); return -1; } m_hMapFile = CreateFileMapping( INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, BUF_SIZE, str.GetBuffer()); if(m_hMapFile == NULL) { AfxMessageBox("CreateFileMapping failed!"); return 1; } m_pBuf = static_cast<LPTSTR>(MapViewOfFile( m_hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, BUF_SIZE)); if(m_pBuf == NULL) { AfxMessageBox("MapViewOfFile failed!"); CloseHandle(m_hMapFile); return 1; } return 0; }
接下来就可以对m_pBuf进行写数据或者读数据了。
写数据:
m_edit6.GetWindowTextA(str); memcpy((void*)m_pBuf, str.GetBuffer(), str.GetLength());
读数据:
LRESULT Cp1Dlg::OnMsg3(WPARAM wParam, LPARAM lParam){ CString str; str.Format("R:\t%s", m_pBuf); m_list2.AddString(str); memset((void*)m_pBuf, 0, BUF_SIZE);//读完之后对这块内存进行清零 return 0; }
读数据我采用的是消息处理函数。因为当一个进程对内存完数据之后,我会发送一个Windows消息通知另一进程,在其收到这条消息后就会调用函数读取数据。
比起SOCKET,的确挺方便的。但是如果两个进程同时对这块内存进行写数据该怎么办呢?这就涉及到进程间同步技术了。不过这个我没有做。
把资源打包上传了。