专注于互联网--专注于架构

最新标签
网站地图
文章索引
Rss订阅

首页 »编程综合 » 映射与函数:使用内存读写函数和内存映射文件通信 »正文

映射与函数:使用内存读写函数和内存映射文件通信

来源: 发布时间:星期二, 2008年12月2日 浏览:27次 评论:0
对于ReadProcessMemory()和WriteProcessMemory()函数的通信方法,在第1章已做介绍。并用它说明了C指针的意义,但有两点需要改进:①接收程序在接收数据时所用的指针代码值不需要事先给定;②内存大小是可以变化的。这里将对内存读写函数的通信方法做一点改进。
3.5.1 使用内存映射文件通信的方法采用内存映射(File Mapping)机制可以将整个文件映射为进程虚拟地址空间的一部分来加以访问。这种方法和实例前面已做了详细介绍,这里不再重复。
3.5.2 使用内存读写函数实现进程间通信的方法要使接收程序获得发送程序的数据指针,可以通过发送消息方法来进行,即通过消息把数据指针从发送程序传递到接收程序。也可以用第1章所介绍的方法:先获得发送程序中的被发送数据指针,然后把这个指针直接赋值给接收数据的程序。但这种方法在实际操作中较困难,使用起来不方便。要使用发送消息的方法来传递指针,就需要定义一个用户消息。可用如下的自定义消息来传递指针,即
const UINT wm_nMemMsg=RegisterWindowMessage("mem_data");

要通过内存来传递数据,还必须要在内存中申请一定的内存空间,这一点很重要。用变量定义的方法只能申请有限的固定的内存空间,例如,定义一个char变量只能在内存里申请到一个字节的内存空间,定义一个int 变量只能在内存里申请到4个字节的内存空间。如果要分配一块内存空间存放数据,可以调用GlobalAlloc()或者VirtualAllocEx()等来实现。
3.5.3 使用内存读写函数实现进程间通信的实例自定义消息和内存读写函数(ReadProcessMemory()和WriteProcessMemory())相结合,利用它们各自的长处进行通信。自定义消息通信只能传递一个长整型数值,而内存读写函数却需要一个内存读写地址,并且缺少一个传递数据指针的方法。这样它们正好可以“合作”,来进行大批量的数据传递工作。
要进行这种方式的通信,同样需要编写两个对话框程序,并且在这两个程序中分别定义一个相同的用于传递指针的消息wm_nMemMsg。这里借用前面所使用的发送数据对话框类CDataSendDlg和接收数据对话框类CDataRecvDlg。在CDataSendDlg中,用MFC ClassWizard工具或手动增加成员函数void CDataSendDlg::OnSendMem(),其源代码如下:
void CDataSendDlg::OnSendMem()
{
UpdateData(); // 更新数据
CWnd *pWnd=CWnd::FindWindow(NULL,_T("DataRecv")); // 查找DataRecv进程
if(pWnd==NULL){
AfxMessageBox("Unable to find DataRecv.");
return;
}
// 获取进程号
DWORD PID;
GetWindowThreadProcessId(pWnd->m_hWnd, (DWORD*)&PID );
HANDLE hProcess = OpenProcess (PROCESS_ALL_ACCESS,FALSE,PID);
// 分配虚拟内存
LPVOID lpBaseAddress;
lpBaseAddress = VirtualAllocEx(hProcess, 0, BUFFER_SIZE,
MEM_COMMIT, PAGE_READWRITE);
char data[BUFFER_SIZE];
strcpy(data,m_strMem);
// 把字符串写入hProcess进程的内存
WriteProcessMemory(hProcess, lpBaseAddress, data, BUFFER_SIZE, NULL);
// 发送基址给DataRecv进程
pWnd->SendMessage(wm_nMemMsg,NULL,(LPARAM)lpBaseAddress);
// 等待接收程序接收数据
Sleep(100);
// 释放虚拟内存
VirtualFreeEx(hProcess,lpBaseAddress, 0, MEM_RELEASE);
}
从以上程序中可以看出如何使用WriteProcessMemory()和wm_nMemMsg消息来发送字符串m_strMem。这段程序中,首先,寻找接收数据的程序DataRecv的窗口指针pWnd和进程句柄hProcess,再用VirtualAllocEx()函数在这个进程中申请虚拟内存空间。然后,用WriteProcessMemory()把字符串m_strMem存放入虚拟内存,并且通过消息wm_nMemMsg把所申请的内存空间起始地址发送给数据接收程序。最后,当数据接收程序接收到数据后,用VirtualFreeEx()释放所申请的虚拟内存。
在数据接收程序的对话框类CDataRecvDlg中,需要定义wm_nMemMsg消息映射,它在消息映射表中的表示方法如下:
BEGIN_MESSAGE_MAP(CDataRecvDlg, CDialog)
//{{AFX_MSG_MAP(CDataRecvDlg)
ON_REGISTERED_MESSAGE(wm_nMemMsg,OnRegMemMsg)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
在数据接收对话框类CDataRecvDlg中,用MFC ClassWizard工具或手动增加消息映射函数void CDataRecvDlg::OnRegMemMsg(),其定义如下:
void CDataRecvDlg::OnRegMemMsg(WPARAM wParam,LPARAM lParam)
{
LPVOID lpBaseAddress=(LPVOID)lParam;
// 把字符串写入hProcess进程的内存
HANDLE hProcess=GetCurrentProcess();
char data[BUFFER_SIZE];
ReadProcessMemory(hProcess, lpBaseAddress, data,BUFFER_SIZE, NULL);
m_strMem=data;
// 更新数据
UpdateData(FALSE);
}

如果本文没有解决您的问题,请进老妖怪开发者社区提问

相关文章

读者评论

  • 共0条 分0页

发表评论

  • 昵称:
  • 内容: