Windows进程间通信之共享内存
之前自己做的一个项目涉及到进程间通信问题,我采用的是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,的确挺方便的。但是如果两个进程同时对这块内存进行写数据该怎么办呢?这就涉及到进程间同步技术了。不过这个我没有做。
把资源打包上传了。

浙公网安备 33010602011771号