VC++ 进程间的通信

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了VC++ 进程间的通信相关的知识,希望对你有一定的参考价值。

进程间如何通信?

线程间通讯

一般而言,应用程序中的一个次要线程总是为主线程执行特定的任务,这样,主线程和次要线程间必定有一个信息传递的渠道,也就是主线程和次要线程间要进行通信。这种线程间的通信不但是难以避免的,而且在多线程编程中也是复杂和频繁的,下面将进行说明。

使用全局变量进行通信

由于属于同一个进程的各个线程共享操作系统分配该进程的资源,故解决线程间通信最简单的一种方法是使用全局变量。对于标准类型的全局变量,我们建议使用volatile 修饰符,它告诉编译器无需对该变量作任何的优化,即无需将它放到一个寄存器中,并且该值可被外部改变。如果线程间所需传递的信息较复杂,我们可以定义一个结构,通过传递指向该结构的指针进行传递信息。

使用自定义消息

我们可以在一个线程的执行函数中向另一个线程发送自定义的消息来达到通信的目的。一个线程向另外一个线程发送消息是通过操作系统实现的。利用Windows操作系统的消息驱动机制,当一个线程发出一条消息时,操作系统首先接收到该消息,然后把该消息转发给目标线程,接收消息的线程必须已经建立了消息循环。
例程7 MultiThread7

该例程演示了如何使用自定义消息进行线程间通信。首先,主线程向CCalculateThread线程发送消息WM_CALCULATE,CCalculateThread线程收到消息后进行计算,再向主线程发送WM_DISPLAY消息,主线程收到该消息后显示计算结果。

建立一个基于对话框的工程MultiThread7,在对话框IDD_MULTITHREAD7_DIALOG中加入三个单选按钮IDC_RADIO1,IDC_RADIO2,IDC_RADIO3,标题分别为1+2+3+4+......+10,1+2+3+4+......+50,1+2+3+4+......+100。加入按钮IDC_SUM,标题为“求和”。加入标签框IDC_STATUS,属性选中“边框”;
在MultiThread7Dlg.h中定义如下变量: protected:
int nAddend;

代表加数的大小。

分别双击三个单选按钮,添加消息响应函数:void CMultiThread7Dlg::OnRadio1()

nAddend=10;


void CMultiThread7Dlg::OnRadio2()

nAddend=50;



void CMultiThread7Dlg::OnRadio3()

nAddend=100;


并在OnInitDialog函数中完成相应的初始化工作: BOOL CMultiThread7Dlg::OnInitDialog()

……
((CButton*)GetDlgItem(IDC_RADIO1))->SetCheck(TRUE);
nAddend=10;
……

在MultiThread7Dlg.h中添加: #include "CalculateThread.h"
#define WM_DISPLAY WM_USER+2
class CMultiThread7Dlg : public CDialog

// Construction
public:
CMultiThread7Dlg(CWnd* pParent = NULL); // standard constructor
CCalculateThread* m_pCalculateThread;
……
protected:
int nAddend;
LRESULT OnDisplay(WPARAM wParam,LPARAM lParam);
……

在MultiThread7Dlg.cpp中添加: BEGIN_MESSAGE_MAP(CMultiThread7Dlg, CDialog)
……
ON_MESSAGE(WM_DISPLAY,OnDisplay)
END_MESSAGE_MAP()

LRESULT CMultiThread7Dlg::OnDisplay(WPARAM wParam,LPARAM lParam)

int nTemp=(int)wParam;
SetDlgItemInt(IDC_STATUS,nTemp,FALSE);

return 0;


以上代码使得主线程类CMultiThread7Dlg可以处理WM_DISPLAY消息,即在IDC_STATUS标签框中显示计算结果。
双击按钮IDC_SUM,添加消息响应函数: void CMultiThread7Dlg::OnSum()

m_pCalculateThread=
(CCalculateThread*)AfxBeginThread(RUNTIME_CLASS(CCalculateThread));

Sleep(500);

m_pCalculateThread->PostThreadMessage(WM_CALCULATE,nAddend,NULL);

OnSum()函数的作用是建立CalculateThread线程,延时给该线程发送WM_CALCULATE消息。
右击工程并选中“New Class…”为工程添加基类为 CWinThread 派生线程类 CCalculateThread。

在文件CalculateThread.h 中添加 #define WM_CALCULATE WM_USER+1
class CCalculateThread : public CWinThread

……
protected:
afx_msg LONG OnCalculate(UINT wParam,LONG lParam);
……

在文件CalculateThread.cpp中添加 LONG CCalculateThread::OnCalculate(UINT wParam,LONG lParam)

int nTmpt=0;
for(int i=0;i<=(int)wParam;i++)

nTmpt=nTmpt+i;


Sleep(500);
::PostMessage((HWND)(GetMainWnd()->GetSafeHwnd()),WM_DISPLAY,nTmpt,NULL);

return 0;

BEGIN_MESSAGE_MAP(CCalculateThread, CWinThread)
//AFX_MSG_MAP(CCalculateThread)
// NOTE - the ClassWizard will add and remove mapping macros here.
//AFX_MSG_MAP
ON_THREAD_MESSAGE(WM_CALCULATE,OnCalculate)
//和主线程对比,注意它们的区别
END_MESSAGE_MAP()

在CalculateThread.cpp文件的开头添加一条: #include "MultiThread7Dlg.h"

以上代码为 CCalculateThread 类添加了 WM_CALCULATE 消息,消息的响应函数是 OnCalculate,其功能是根据参数 wParam 的值,进行累加,累加结果在临时变量nTmpt中,延时0.5秒,向主线程发送WM_DISPLAY消息进行显示,nTmpt作为参数传递。
编译并运行该例程,体会如何在线程间传递消息。
参考技术A 可以有很多中方式:
1.命名管道
2.匿名管道
3.邮槽
4.剪贴板
5.WM_COPYDATA
6.WM_SETTEXT
7.数据共享
8.Socket

说说最简单的WM_COPYDATA
你可以向一个窗口发送WM_COPYDATA消息,用SendMessage
比如你向一个窗口通宵,想发送一个字符串"CIW_BLUE"给另外一个窗口,可以这样:
COPYDATASTRUCT stCopyData = 0;
stCopyData.lpData = "CIW_BLUE";
stCopyData.cbData = strlen("CIW_BLUE")+ 1;
SendMessage(hWnd, WM_COPYDATA, 0, (LPARAM)&stCopyData);

你在接受的程序里面响应WM_COPYDATA消息就OK
lParam 是一个COPYDATASTRUCT的指针

其他实现起来比较复杂 以后你慢慢研究本回答被提问者采纳
参考技术B 进程之间通过消息来进行通信
具体可参考window编程的相关书目

Linux进程间的通信方法简介

一、本地进程间的通信方式:

    1.管道(pipe)

        利用管道文件可以进行进程间数据的通信,通常是具有血缘关系的父子进程间的通信方式。

        管道通信为半双工模式,父子进程可以通过调用内核中的read()和write()命令来向管道文件进行读写操作。

        管道通信是基于硬盘内的文件,所以I/O速度较低。


    2.消息队列

        消息队列是一种类似链表的数据结构,存放于内存中,因此I/O速度较管道更快,通过ipcs -q命令可以查看当前系统中被创建的消息队列。

        多个不同进程可以使用同一个消息队列进行通信,消息队列中的数据是以块存放,每块数据有特定的mtype,进程在发送和接收数据的时候必须指定特定的mtype。


    3.信号量

        用于处理进程的同步和互斥:

            同步:严格安排进程执行的先后顺序

            互斥:两个进程不可以同时使用同一资源(代码段),可以说是特殊的同步

        信号量可以理解为一个计数器,当有进程申请使用信号量时,将其计数-1(P操作),当计数器为0时表示此时没有资源,其他进程要访问必须等待,当一个进程使用完毕资源时,将其计数+1(V操作)。


    4.共享内存

        类似消息队列,但操作更为简洁,通过ipcs -m命令可以查看当前系统中被创建的共享内存区。

        进程想使用共享内存区时,需要先创建对该共享内存的链接。


二、不同主机进程间的通信(网络通信)

    通过两台主机的一对套接字来进行通信,套接字由ip地址和端口号组成,一个套接字标识特定主机的特定进程。

    服务器进程创建套接字,将其设置监听状态,这种进程称为守护进程。

    之后客户端创建用于请求链接的套接字,对服务器处于监听状态的套接字发出链接请求,从而建立链接。


    

以上是关于VC++ 进程间的通信的主要内容,如果未能解决你的问题,请参考以下文章

C内存共享进程通信范例

进程间的通信——pipe通信

进程间的通信

进程通信,线程通信,同步方式

Python进程间的通信之管道通信:os.pipe

Python进程间的通信之管道通信:os.pipe