进程通信Word文档下载推荐.docx

上传人:b****5 文档编号:19875019 上传时间:2023-01-11 格式:DOCX 页数:28 大小:69.42KB
下载 相关 举报
进程通信Word文档下载推荐.docx_第1页
第1页 / 共28页
进程通信Word文档下载推荐.docx_第2页
第2页 / 共28页
进程通信Word文档下载推荐.docx_第3页
第3页 / 共28页
进程通信Word文档下载推荐.docx_第4页
第4页 / 共28页
进程通信Word文档下载推荐.docx_第5页
第5页 / 共28页
点击查看更多>>
下载资源
资源描述

进程通信Word文档下载推荐.docx

《进程通信Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《进程通信Word文档下载推荐.docx(28页珍藏版)》请在冰豆网上搜索。

进程通信Word文档下载推荐.docx

同时给出了发送数据程序和接收数据程序的主要源代码。

图3.1和图3.2是本章开发的进程之间通信程序的演示对话框。

进程间通信是一个非常复杂的过程,涉及的问题也较多,例如进程互斥和同步等,这些问题在本书中不做介绍。

发送数据程序对话框 

接收数据程序对话框

3.2 

在学习编写进程之间通信的程序之前,有必要先介绍一些有关的背景知识,这样有助于读者对一些有关进程间通信方面的概念有较深入的了解。

3.2.1 

Windows进程间标准通信技术的发展

我们既可以用非标准的进程间通信技术,如Windows消息、内存映射和内存共享等,也可以用标准的通信技术。

微软标准进程间通信技术的发展过程如下所述。

(1)进程间通信初期

自从有Windows操作系统后,剪贴板(Clipboard)首先解决了不同程序间的通信问题(由剪贴板作为数据交换中心,进行复制、粘贴的操作)。

但是剪贴板传递的都是“死”数据,应用程序开发者得自行编写、解析数据格式的代码。

于是动态数据交换(DynamicDataExchange,DDE)的通信协定应运而生,它可以让应用程序之间自动获取彼此的最新数据。

但是,解决彼此之间的数据格式转换仍然是程序员沉重的负担。

对象的链接和嵌入(ObjectLinkingandEmbedded,OLE)的诞生把原来应用程序的数据交换提高到“对象交换”,这样程序间不但获得数据,而且也可以获得彼此的对象,并且可以直接使用彼此数据内容。

(2)OLE(对象链接与嵌入)

1991年制定的OLE1.0规范主要解决多个应用程序之间的通信和消息传递问题,微软希望第三方开发商能够遵守这个规范,以便在当时的Windows平台上的应用程序能够相互协调工作,更大地提高工作效率。

然而事与愿违,只有很少的软件开发商支持它。

为此,微软于1993年发布了新的规范——OLE2.0,它在原有的基础上完善并增强了以下各方面的性能:

①OLE自动化,一个程序有计划地控制另一个程序的能力;

②OLE控件,小型的组件程序,可嵌入到另外的程序,提供自己的专有功能;

③OLE文档,完善了早期的混合文档功能,不仅支持简单的链接和嵌入,还支持在位激活、拖放等功能。

(3)ActiveX战略

同OLE1.0相比,OLE2.0得到了很多软件厂商的支持。

许多程序设计人员编写了大量的实现OLE自动化服务器功能的组件(不一定是EXE文件),这些组件一般不求功能齐全、强大,而是可以实现专门的功能,被其他程序编程控制,由此承袭OLE的名字,称为OLE控件。

它们在文件名中的扩展名一般为ocx(OLEControlExtension)。

微软刚刚赢得广大软件厂商的支持,使OLE技术深入人心,然而天不如人愿,国际互联网的超速发展让比尔·

盖茨始料未及。

加上早期的OLE1.0不得人心,导致后来的人们总把在Word中插入一个图形当作OLE技术的全部,各类资料在介绍新OLE技术时命名也不统一,造成很大的混乱。

针对这些情况,微软在1996年重新制订了一个关于OLE的规 

范——OLE96。

这个规范扩展了OLE控件的能力,并贯彻微软的Internet战略使它更易于在网络环境中使用,还考虑命名混淆的问题,重新给OLE控件贴上一个标签——ActiveX控件。

不仅如此,以前的什么OLE文档也相应称为ActiveX文档了。

总之,为了满足Internet战略,微软把OLE换成了ActiveX,企图使人们重新看待新的OLE——ActiveX,把它看成网络上的解决软件组件问题的标准。

(4)OLE/ActiveX与COM/DCOM比较

OLE/ActiveX名称比COM/DCOM更为我们熟悉,其实OLE和ActiveX是商业名称,它们的发展过程为OLE→ActiveX(网络OLE)。

COM和DCOM是纯技术名词,它们是OLE/ActiveX基础,其发展过程为COM→DCOM(网络COM),其中COM(ComponentObjectModel,组件对象模式)是在OLE2.0中建立的规范。

OLE/ActiveX不仅可以实现进程之间的通信,而且可以创建进程,它们是“类厂”组件对象。

3.2.2 

应用程序与进程

应用程序和进程在概念上是有一定区别的,前者是静态的程序代码,而后者是动态的实体。

只有应用程序加载到系统中后才能成为一个进程。

Windows进程分为独立进程和共享进程两种。

一般情况下,人们把独立运行的程序称为进程,其实这只是独立进程。

在实际情况下也常常遇到另一种情况,即一个应用程序可能启动多个进程,一个进程空间可以运行多个程序,这就是共享进程。

例如,同一个应用程序重复运行就启动了多个进程;

而在一个进程中调用其他程序,或者通过程序挂钩,这就使同一个进程空间里运行了多个程序。

这里着重讨论独立进程之间的通信。

3.2.3 

进程之间通信的类型

根据不同的标准,进程之间通信类型有不同的划分方法。

实际中也有多种划分方法,这里只给出几种划分方法如下所述。

(1)低级通信和高级通信

·

低级通信:

只能传递状态和整数值(控制信息),包括进程互斥和同步所采用的信号量和管程机制。

其第一个缺点为传送信息量小、效率低,每次通信传递的信息量固定,若传递较多信息则需要进行多次通信;

第二个缺点是编程复杂,直接实现通信的细节,容易出错。

高级通信:

能够传送任意数量的数据,包括共享存储区、管道、消息等。

(2)直接通信和间接通信

直接通信:

信息直接传递给接收方,如管道,在发送时,指定接收方的地址或标识,也可以指定多个接收方或广播式地址;

在接收时,允许接收来自任意发送方的消息,并在读出消息的同时获取发送方的地址。

间接通信:

借助于收发双方进程之外的共享数据结构作为通信中转,如剪贴板。

通常接收和发送方的数目可以是任意的。

(3)本地通信和远程通信

本地通信方式:

这种通信又称之为同机通信,它是在同一台计算机上的程序之间进行的,也就是说客户进程和服务进程位于同一台计算机上。

远程通信方式:

这种通信又称之为网间的进程通信,要解决的是不同主机进程间的相互通信问题(可把同机进程通信看作是其中的特例)。

在这种通信中,首先要解决的是网络间的进程标识问题。

同一主机上,不同进程可用进程号(processID)唯一标识。

但在网络环境下,各主机独立分配的进程号不能唯一标识该进程。

例如,主机A赋予某个进程号5,在B机中也可以存在5号进程,因此,“5号进程”这句话就没有意义了。

其次,操作系统支持的网络协议众多,不同协议的工作方式不同,地址格式也不同。

因此,网间的进程通信还要解决多重协议的识别问题。

3.3 

使用自定义消息通信

Windows程序与其他类型程序的区别就是使用消息,例如键盘或鼠标消息等,在DOS系统下的程序没有定义消息。

在Windows操作系统中,消息不但可以用于进程内的通信,也可以用于进程间的通信。

这里重点介绍进程间的消息通信。

3.3.1 

通过自定义消息实现进程间通信的方法

消息分为两种,即系统消息和用户(程序设计者)自定义消息。

系统消息定义从0到0x3FF,可以使用0x400到0x7FFF定义自己的消息。

Windows把0x400定义为WM_USER。

如果想定义自己的一个消息,可以在WM_USER上加上一个值。

还有一种自定义窗口消息的方法是用RegisterWindowsMessage()函数来注册这个消息。

与在WM_USER上加上某个数相比,它的好处是不必考虑所表示的消息标识符是否超出工程的允许范围。

要想用消息实现进程间通信,则需要在这两个程序中定义或注册相同的消息,才能保证数据通信顺利进行。

用户自定义消息的方法如下:

 

#defineWM_COMM 

WM_USER+100

constUINTwm_nRegMsg=RegisterWindowMessage("

reg_data"

);

有了这两种定义的消息后,可以用如下的方法来发送消息。

pWnd->

SendMessage(WM_COMM,NULL,(LPARAM)uMsg);

SendMessage(wm_nRegMsg,NULL,(LPARAM)uMsg);

其中pWnd为接收这个消息的窗口句柄,uMsg为要通过消息发送的数据,是长整型。

这两个消息的发送可以分别在一个发送函数里实现,其具体的做法见以后的实例。

通过实验可知,这两种自定义消息的发送效果是一样的。

在接收消息的程序中,除与发送消息的程序需要定义相同的消息外,还需要定义相应的消息映射和消息映射函数,消息的映射方法如下:

ON_MESSAGE(WM_COMM,OnUserReceiveMsg)

ON_REGISTERED_MESSAGE(wm_nRegMsg,OnRegReceiveMsg)

与以上消息映射对应的函数定义如下:

voidCDataRecvDlg:

:

OnUserReceiveMsg(WPARAMwParam,LPARAMlParam)

{

//增加用户自定义程序代码

}

//--------------------------------------------------------------------

OnRegReceiveMsg(WPARAMwParam,LPARAMlParam)

//增加用户自定义程序代码

其中OnUserReceiveMsg()函数为WM_COMM消息的映射函数,OnRegReceiveMsg()函数为wm_nRegMsg消息的映射函数。

可以看出,这两种消息的映射函数形式是一样的。

3.3.2 

通过自定义消息实现进程间通信的实例

为说明以自定义消息实现进程之间的通信,作者用VC++编写了这样的程序。

有两个对话框程序,其中一个为发送程序,另一个为接收程序。

在这两个程序中分别定义了两个消息WM_COMM和wm_nRegMsg,在CDataSendDlg类中增加了用于发送数据的两个函数,即voidCDataSendDlg:

OnSendUsermsg()和voidCDataSendDlg:

OnSendRegmsg()。

它们的源代码如下:

voidCDataSendDlg:

OnSendUsermsg()

UpdateData();

//更新数据

CWnd*pWnd=CWnd:

FindWindow(NULL,_T("

DataRecv"

));

//查找DataRecv进程

if(pWnd==NULL){

AfxMessageBox(TEXT("

UnabletofindDataRecv."

return;

}

UINTuMsg;

uMsg=atoi(m_strUserMsg);

pWnd->

//发送.

OnSendRegmsg()

AfxMessageBox("

uMsg=atoi(m_strRegMsg);

//发送

在接收数据的程序中要做三件事:

①定义自定义消息;

②定义消息映射表;

③定义消息映射函数。

自定义消息的方法如前面所述。

在CDataRecvDlg类中增加了两个用于接收数据的函数,即voidCDataRecvDlg:

OnUserReceiveMsg()和voidCDataRecvDlg:

OnRegReceiveMsg()。

消息映射表如下:

BEGIN_MESSAGE_MAP(CDataRecvDlg,CDialog)

//{{AFX_MSG_MAP(CDataRecvDlg)

ON_MESSAGE(WM_COMM,OnUserReceiveMsg)

ON_REGISTERED_MESSAGE(wm_nRegMsg,OnRegReceiveMsg)

//}}AFX_MSG_MAP

END_MESSAGE_MAP()

消息映射表中的映射函数名的格式是一样的。

其实它们可以用同一个函数,为了说明方便,这里把它们的名字取为不一样。

接收数据程序中的消息映射函数的源代码如下:

m_strUserMsg.Format("

%d\n"

int(lParam));

UpdateData(FALSE);

m_strRegMsg.Format("

从上面的实例中可以看出,以自定义消息来进行进程之间的通信存在一定的局限性,即所发送的数据只能是长整型,而对于字符串,则不能进行通信。

要进行字符串或大批量的数据的传输,则需要采用其他的通信方法。

3.4 

使用WM_COPYDATA消息通信

对于少量数据可以用WM_COPYDATA方便地实现通信。

由于SendMessage()是阻塞的,只有接收方响应了消息,SendMessage()才能返回,否则一直阻塞。

所以,对于大量数据来说,用SendMessage()就容易造成窗口假死。

3.4.1 

通过WM_COPYDATA消息实现进程间通信的方法

在Win32中,WM_COPYDATA消息主要目的是允许在进程间传递只读数据。

SDK文档推荐用户使用SendMessage()函数,接收方在数据复制完成前不返回,这样发送方就不可能删除和修改数据。

这个函数的原型如下:

SendMessage(WM_COPYDATA,wParam,lParam)

其中wParam设置为包含数据的窗口句柄,lParam指向一个COPYDATASTRUCT的结构,其定义为:

typedefstructtagCOPYDATASTRUCT{

DWORDdwData;

DWORDcbData;

PVOIDlpData;

}COPYDATASTRUCT;

其中dwData为自定义数据,cbData为数据大小,lpData为指向数据的指针。

需要注意的是,WM_COPYDATA消息保证发送的数据从原进程复制到目标进程。

但是,WM_COPYDATA消息不能发送HDC、HBITMAP之类的东西,它们对于目标进程来说是无效的。

目标进程得到这些数据不能在原进程作任何事情,因为它们属于不同的进程。

与其他进程通信方法一样,要实现进程间的数据通信,在发送数据的程序中,首先要找到接收数据进程的窗口句柄pWnd,可以用CWnd:

FindWindow(NULL,_T("

))函数来得到,其中字符串"

为接收数据的程序名。

然后用SendMessage()函数发送数据,其具体的做法见后面的实例。

在接收数据的程序中,首先在消息映射表中增加WM_COPYDATA消息映射,然后定义消息映射函数,其函数的格式为:

BOOLCDataRecvDlg:

OnCopyData(CWnd*pWnd,COPYDATASTRUCT*pCopyDataStruct)

3.4.2 

通过WM_COPYDATA消息实现进程间通信的实例

与前面所说的自定义消息不一样,WM_COPYDATA消息是Win32提供的消息。

与自定义消息相比较,WM_COPYDATA消息可以传递一个较大的数据块。

这里仍然用两个对话框程序来实现WM_COPYDATA消息的通信。

以下分别给出发送数据程序的发送函数和接收数据程序的接收函数。

在发送数据的对话框类CDataSendDlg中,用MFCClassWizard工具或者手工的方法增加函数voidCDataSendDlg:

OnSendCopydata(),其具体代码如下:

OnSendCopydata()

COPYDATASTRUCTcpd;

//给COPYDATASTRUCT结构赋值

cpd.dwData=0;

cpd.cbData=m_strCopyData.GetLength();

cpd.lpData=(void*)m_strCopyData.GetBuffer(cpd.cbData);

SendMessage(WM_COPYDATA,NULL,(LPARAM)&

cpd);

在用MFCAppWizard(exe)创建接收数据的对话框程序后,生成对话框类CDataRecvDlg。

在这个类中,首先要定义接收WM_COPYDATA消息的映射,可以用ClassWizard工具来增加,也可以手动增加,但手动增加需要修改三个地方:

①在消息映射表中增加ON_WM_COPYDATA();

②增加成员函数BOOLCDataRecvDlg:

OnCopyData();

③在CDataRecvDlg类中增加WM_COPYDATA消息映射函数的定义。

WM_COPYDATA消息的映射如下:

ON_WM_COPYDATA()

CDataRecvDlg:

OnCopyData()函数的定义如下:

m_strCopyData=(LPSTR)pCopyDataStruct->

lpData;

//获得实际长度的字符串

m_strCopyData=m_strCopyData.Left(pCopyDataStruct->

cbData);

returnCDialog:

OnCopyData(pWnd,pCopyDataStruct);

其中m_strCopyData为接收到的字符串,pCopyDataStruct为COPYDATASTRUCT结构指针。

注意由pCopyDataStruct直接得到的m_strCopyData字符串长度可能不是实际发送的字符串长度,需要用发送字符串时所给定的字符串长度来进一步确定,其长度由pCopyDataStruct->

cbData来得到。

3.5 

对于ReadProcessMemory()和WriteProcessMemory()函数的通信方法,在第1章已做介绍。

并用它说明了C指针的意义,但有两点需要改进:

①接收程序在接收数据时所用的指针代码值不需要事先给定;

②内存大小是可以变化的。

这里将对内存读写函数的通信方法做一点改进。

3.5.1 

使用内存映射文件通信的方法

采用内存映射(FileMapping)机制可以将整个文件映射为进程虚拟地址空间的一部分来

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 自然科学 > 数学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1