文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php文档>进程之间通讯,发送自定义消息/发送WM_COPYDATA消息/发送线程消息/以及内存映射方式

进程之间通讯,发送自定义消息/发送WM_COPYDATA消息/发送线程消息/以及内存映射方式

时间:2010-08-25  来源:散客游

打开VC6,创建两个MFC对话框工程,ProcessA和ProcessB

 

 1.发送自定义消息方式:

   优点:简单,方便

   缺点:能发送的数据太小,需要接收消息进程有窗口

   用到的函数:

     FindWindow //查找窗口

     PostMessage //发送消息到指定窗口的消息队列,发送后立即返回

     SendMessage //发送消息到指定窗口,直到接收窗口程序处理完消息再返回

  ProcessA:

    //找窗口句柄
   HWND hWnd = ::FindWindow(NULL, "ProcessB");
    if (hWnd == NULL)
    {
        return;
    }

    //把10发送给进程B
    DWORD dwNum = 10;
    //向进程B消息队列投递一个自定义消息 WM_USER + 1
    //::PostMessage(hWnd, WM_USER + 1, dwNum, NULL);

    //直接向进程B发送一个 WM_USER + 1
    ::SendMessage(hWnd, WM_USER + 1, dwNum, NULL);

  

   ProcessB:

CString txt;
txt.Format("数值:%d", wParam);
AfxMessageBox(txt);

 

 

2.发送WM_COPYDATA消息

  优点:简单,方便,可以发送稍大的数据,由操作系统管理接收方进程的内存申请和释放,不用自己去管理

  缺点:数据量太大时,可能会造成进程A卡住,需要接收消息进程有窗口

  用到的函数:

    FindWindow //查找窗口

    SendMessage //发送消息到指定窗口,直到接收窗口程序处理完消息再返回

   ProcessA:

   //找窗口句柄
  HWND hWnd = ::FindWindow(NULL, "ProcessB");
    if (hWnd == NULL)
    {
        return;
    }

    //要发送的字符串
    char szBuff[] = "hello world!";

    //WM_COPYDATA 需要发送一个结构体
    COPYDATASTRUCT cds = {0};
    cds.lpData = szBuff;                    //要发送内容的首地址
    cds.cbData = strlen(szBuff) + 1;        //要发送多大内容
    cds.dwData = 0;                         //附加参数,如果需要可以随便改变这里的值

    //直接向进程B发送一个 WM_COPYDATA 消息
    //注意,发送WM_COPYDATA消息,不能用PostMessage,MSDN有明确说明.
    ::SendMessage(hWnd,                     //接收消息的窗口句柄
                  WM_COPYDATA,              //消息类型
                  (WPARAM)GetSafeHwnd(),    //发送消息的窗口句柄,既进程A的窗口句柄
                  (LPARAM)&cds);            //要发送的内容

 

  ProcessB:

 //因为lpData是一个LPVOID,void*指针,所以需要强转一下
 AfxMessageBox((LPTSTR)pCopyDataStruct->lpData);

 

3.发送线程消息:

  优点:简单,方便

  缺点:能发送的数据太小

  用到的函数:

    FindWindow //查找窗口

    GetWindowThreadProcessId //获取指定窗口的进程ID和主线程ID

    PostThreadMessage//发送消息到指定线程

 

  如果是向主线程发送消息,接收线程消息的进程,可以覆盖虚函数PreTranslateMessage来完成消息的处理

 

   ProcessA:

   //找窗口句柄
  HWND hWnd = ::FindWindow(NULL, "ProcessB");
    if (hWnd == NULL)
    {
        return;
    }

    //主线程ID
    DWORD dwThreadID = 0;
    //获取指定窗口主线程ID, 第二个参数是进程ID out 传出值.
    dwThreadID = ::GetWindowThreadProcessId(hWnd, NULL);

    //向主线程发送线程消息
  BOOL bRet = ::PostThreadMessage(dwThreadID, WM_USER + 2, 1, 2);
    if (!bRet)
    {
        AfxMessageBox("发送线程消息失败!");
    }

 

  ProcessB:

BOOL CProcessBDlg::PreTranslateMessage(MSG* pMsg) 
{
    // TODO: Add your specialized code here and/or call the base class
    if(pMsg->message == WM_USER + 2)
    {
        CString txt;
        txt.Format("参数1:%d,参数2:%d", pMsg->wParam, pMsg->lParam);
        AfxMessageBox(txt);
        return TRUE;
    }
    
    return CDialog::PreTranslateMessage(pMsg);
}

 

4.内存映射方式:

  优点:多个进程可以通过虚拟内存映射到同一块物理内存存进行操作,实现数据共享,不要求进程有窗口

  缺点:操作稍微有点麻烦

  用到的函数:

    CreateFileMapping //在物理内存中开辟一块指定大小的空间

    MapViewOfFile //建立一块本进程的虚拟内存和映射对象管理的物理内存建立映射,但实际上的物理内存页面并没有分配,这个时候,如果你要写这片内存的话,才会出现物理内存页面的分配

    UnmapViewOfFile //解除本进程的虚拟内存和映射对象管理的物理内存的映射

    CloseHandle //对对象进行引用计数-1

    OpenFileMapping //根据映射对象的名称打开内存映射

    

 这种方式用的人很多,个人也比较喜欢,但需要说明的是,CreateFileMapping返回的映射对象控制句柄,最好不要定义成局部变量,当函数执行完毕之后,局部变量就会销毁,应该会导致对象引用计数-1,这样的话别的进程就无法映射开辟的这块物理内存了,最好保存成类的成员变量,在对话框的OnClose()函数的时候进行一次CloseHandle,CloseHandle会进行对象的引用计数-1,当计数到0的时候,由系统最后回收资源

  ProcessA:

void CProcessADlg::OnBtnFileMapping()
{
    // TODO: Add your control notification handler code here

    //创建内存映射对象,建立用于共享的物理内存,第一个参数,如果给文件句柄,则是文件映射
    m_hMap = ::CreateFileMapping(INVALID_HANDLE_VALUE,  //-1值,代表这是一个内存映射
                                        NULL,                 //返回的句柄是否可以通过子进程继承
                                        PAGE_READWRITE,       //读写属性
                                        0,                    //高位大小 因为文件可能超过4G,所以有可能会有值
                                        0x1000,               //低位大小,创建多大的内存
                                        "MyMap");             //映射对象的名称
    if (m_hMap == NULL)
    {
        AfxMessageBox("创建内存映射失败!");
        return;
    }

    //建立一块本进程的虚拟内存 和 映射对象管理的物理内存 建立映射
    LPVOID lpMem =  MapViewOfFile(m_hMap,               //内存映射控制对象
                                  FILE_MAP_ALL_ACCESS,  //访问权限
                                  0,                    //高位偏移
                                  0,                    //低位偏移
                                  0x1000);              //大小
    if (lpMem == NULL)
    {
        //引用计数-1,销毁对象
        CloseHandle(m_hMap);
        m_hMap = NULL;
        AfxMessageBox("映射内存失败!");
        return;
    }

    //往内存中写入内容.lpMem是void* 所以做一下强转
    strcpy((LPTSTR)lpMem, "hello world!");


    //解除映射
    //取消本进程的 虚拟内存 和 映射对象管理的物理内存 的 映射
    if (!UnmapViewOfFile(lpMem))
    {
        //引用计数-1,销毁对象
        CloseHandle(m_hMap);
        m_hMap = NULL;
        AfxMessageBox("解除内存映射失败!");
    }

}

 

  ProcessB:

void CProcessBDlg::OnBtnFileMapping()
{
    // TODO: Add your control notification handler code here

    //根据映射对象的名称打开内存映射,会使内存映射控制对象引用计数+1
    HANDLE hMap = OpenFileMapping(FILE_MAP_ALL_ACCESS,  //访问权限
                                  NULL,                 //返回的句柄是否可以通过子进程继承
                                  "MyMap");             //映射对象的名称
    if (hMap == NULL)
    {
        AfxMessageBox("打开内存映射失败!");
        return;
    }

    //建立一块本进程的虚拟内存 和 映射对象管理的物理内存 建立映射
    LPVOID lpMem =  MapViewOfFile(hMap,               //内存映射控制对象
                                  FILE_MAP_ALL_ACCESS,  //访问权限
                                  0,                    //高位偏移
                                  0,                    //低位偏移
                                  0x1000);              //大小
    if (lpMem == NULL)
    {
        AfxMessageBox("映射内存失败!");
    }
    else
    {
        //把内存中的东西读出来,并显示.
        AfxMessageBox((LPTSTR)lpMem);
        //解除映射
        //取消本进程的虚拟内存 和 映射对象管理的物理内存 的 映射
        if (!UnmapViewOfFile(lpMem))
        {
            AfxMessageBox("解除内存映射失败!");
        }
    }

    //引用计数-1,因为使用OpenFileMapping,会使内存映射控制对象引用计数+1
    CloseHandle(hMap);
    hMap = NULL;
}

 

完整源码下载地址

http://files.cnblogs.com/sankeyou/%e8%bf%9b%e7%a8%8b%e9%97%b4%e9%80%9a%e8%ae%af.rar

相关阅读 更多 +
排行榜 更多 +
幸存者的命运

幸存者的命运

飞行射击 下载
精英战区3d

精英战区3d

飞行射击 下载
货运猎人

货运猎人

飞行射击 下载