如何实现进程间数据通讯技术

2008-02-23 05:36:21来源:互联网 阅读 ()

新老客户大回馈,云服务器低至5折

1、引言

  在Windows程式中,各个进程之间常常需要交换数据,进行数据通讯。WIN32 API提供了许多函数使我们能够方便高效地进行进程间的通讯,通过这些函数我们能够控制不同进程间的数据交换,就如同在WIN16中对本地进程进行读写操作相同。
  典型的WIN16两进程能够通过共享内存来进行数据交换:(1)进程A将GlobalAlloc(GMEM_SHARE...)API分配一定长度的内存;(2)进程A将GlobalAlloc函数返回的句柄传递给进程B(通过一个登录消息);(3)进程B对这个句柄调用GlobalLock函数,并利用GlobalLock函数返回的指针访问数据。这种方法在WIN32中可能失败,这是因为GlobalLock函数返回指向的是进程A的内存,由于进程使用的是虚拟地址而非实际物理地址,因此这一指针仅和A进程有关,而于B进程无关。
  本文探讨了几种WIN32下进程之间通讯的几种实现方法,读者能够使用不同的方法以达到程式运行高效可靠的目的。

2、Windows95中进程的内存空间管理

  WIN32进程间通讯和Windows95的内存管理有密切关系,理解Windows95的内存管理对我们如下的程式设计将会有很大的帮助,下面我们讨论以下Windows95中进程的内存空间管理。
  在WIN16下,任何Windows应用程式共享单一地址,任何进程都能够对这一空间中属于共享单一的地址空间和属于其他进程的内存进行读写操作,甚至能够存取操作系统本身的数据,这样就可能破坏其他程式的数据段代码。
  在WIN32下,每个进程都有自己的地址空间,一个WIN32进程不能存取另一个地址的私有数据,两个进程能够用具备相同值的指针寻址,但所读写的只是他们各自的数据,这样就减少了进程之间的相互干扰。另一方面,每个WIN32进程拥有4GB的地址空间,但并不代表他真正拥有4GB的实际物理内存,而只是操作系统利用CPU的内存分配功能提供的虚拟地址空间。在一般情况下,绝大多数虚拟地址并没有物理内存和他对应,在真正能够使用这些地址空间之前,还要由操作系统提供实际的物理内存(这个过程叫“提交”commit)。在不同的情况下,系统提交的物理内存是不同的,可能是RAM,也可能是硬盘模拟的虚拟内存。

3、WIN32中进程间的通讯

  在Windows 95中,为实现进程间平等的数据交换,用户能够有如下几种选择:
  * 使用内存映射文档
  * 通过共享内存DLL共享内存
  * 向另一进程发送WM_COPYDATA消息
  * 调用ReadProcessMemory连同WriteProcessMemory函数,用户能够发送由GlobalLock(GMEM_SHARE,...)函数调用提取的句柄、GlobalLock函数返回的指针连同VirtualAlloc函数返回的指针。

--3.1、利用内存映射文档实现WIN32进程间的通讯

  Windows95中的内存映射文档的机制为我们高效地操作文档提供了一种途径,他允许我们在WIN32进程中保留一段内存区域,把目标文档映射到这段虚拟内存中。在程式实现中必须考虑各进程之间的同步。具体实现步骤如下:
  首先我们在发送数据的进程中需要通过调用内存映射API函数CreateFileMapping创建一个有名的共享内存:
  HANDLE CreateFileMapping(
  HANDLE hFile, // 映射文档的句柄,
  //设为0xFFFFFFFF以创建一个进程间共享的对象
  LPSECURITY_ATTRIBUTES lpFileMappingAttributes, // 安全属性
  DWORD flProtect, // 保护方式
  DWORD dwMaximumSizeHigh, //对象的大小
  DWORD dwMaximumSizeLow,
  LPCTSTR lpName // 必须为映射文档命名
  );
  和虚拟内存类似,保护方式能够是PAGE_READONLY或是PAGE_READWRITE。假如多进程都对同一共享内存进行写访问,则必须保持相互间同步。映射文档还能够指定PAGE_WRITECOPY标志,能够确保其原始数据不会遭到破坏,同时允许其他进程在必要时自由地操作数据的拷贝。
  在创建文档映射对象后使用能够调用MapViewOfFile函数映射到本进程的地址空间内。
  下面说明创建一个名为MySharedMem的长度为4096字节的有名映射文档:
  HANDLE hMySharedMapFile=CreateFileMapping((HANDLE)0xFFFFFFFF),
  NULL,PAGE_READWRITE,0,0x1000,“MySharedMem”);
  并映射缓存区视图:
  LPSTR pszMySharedMapView=(LPSTR)MapViewOfFile(hMySharedMapFile,
  FILE_MAP_READ|FILE_MAP_WRITE,0,0,0);
  其他进程访问共享对象,需要获得对象名并调用OpenFileMapping函数。
  HANDLE hMySharedMapFile=OpenFileMapping(FILE_MAP_WRITE,
  FALSE,“MySharedMem");
  一旦其他进程获得映射对象的句柄,能够像创建进程那样调用MapViewOfFile函数来映射对象视图。用户能够使用该对象视图来进行数据读写操作,以达到数据通讯的目的。
  当用户进程结束使用共享内存后,调用UnmapViewOfFile函数以取消其地址空间内的视图:
  if (!UnmapViewOfFile(pszMySharedMap
  View))
  { AfxMessageBox(“could not unmap view of file"); }

--3.2、利用共享内存DLL

  共享数据DLL允许进程以类似于Windows 3.1 DLL共享数据的方式访问读写数据,多个进程都能够对该共享数据DLL进行数据操作,达到共享数据的目的。在WIN32中为建立共享内存,必须执行以下步骤:
  首先创建一个有名的数据区。这在Visual C++中是使用data_seg pragma宏。使用data_seg pragma宏必须注意数据的初始化:
  #pragma data_seg(“MYSEC")
  char MySharedData[4096]={0};
  #pragma data_seg()
  然后在用户的DEF文档中为有名的数据区设定共享属性。
  LIBRARY TEST
  DATA READ WRITE
  SECTIONS
  .MYSEC READ WRITE SHARED
  这样每个附属于DLL的进程都将接受到属于自己的数据拷贝,一个进程的数据变化并不会反映到其他进程的数据中。
  在DEF文档中适当地输出数据。以下的DEF文档项说明了如何以常数变量的形式输出MySharedData。
  EXPORTS
  MySharedData CONSTANT
  最后在应用程式(进程)按外部变量引用共享数据。
  extern _export"C"{char * MySharedData[]}
  进程中使用该变量应注意间接引用。
  m_pStatic=(CEdit*)GetDlgItem(IDC_SHARED);

标签:

版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有

上一篇: 怎样用代码来最小化或恢复程式

下一篇: 用C 品尝Vista美味[2]