张静盛老师目前在盛大网络从事技术研究工作,他从2005年开始担任知名技术社区Windows编程版主,网名“北极星”被很多技术爱好者所熟知。2008年6月份,张静盛推出他的第一本个人技术图书《Windows编程循序渐进》,上市一个月来取得了很好的销售成绩。
在一个多小时的在线沟通过程中,张静盛老师回答了网友数十个经典问题,以下为聊天实录,略有整理。
进程间通信基本知识
主持人:什么是进程间通信?常见有哪些进程间通信方式有哪些?请张老师先给大家普及一下基础知识吧。
张静盛:首先得了解什么是进程。进程是一个正在运行的程序的实例,主要由两部分组成:(1)一个操作系统用来管理进程的内核对象。(2)创建时系统所分配的资源,主要是内存地址空间。
进程间通信是指在多进程环境下,使用的数据交互、事件通知等方法使各进程协同工作。常用的有4种:消息传递、共享内存、管道、剪贴板:
(1)消息传递:不以进程为界限,处理消息的是窗体(包括子窗体、控件等),而与是否在同一进程无关。
(2)共享内存:在一个进程内创建内存映射,却能够在其他都个进程中使用。这些进程共享的是物理存储器的同一个页面,在把这些物理内存映射到虚拟内存时各个进程的虚拟地址并不一定相同。当一个进程将数据写入共享内存时,其他进程可以立即获取数据变更情况。
(3)管道和邮槽:其实是对共享内存的两种不同的封装机制。
(4)剪贴板:Windows系统支持剪贴板IPC的基本机制是由系统预留的一块全局共享内存,可用于被各进程暂时存储数据。写入进程首先创建一个全局内存块,并将数据写到该内存块;接受数据的进程通过剪贴板机制获取此内存块的句柄,并完成对该内存块数据的读取。
主持人:刚才已经有网友提到了使用文件映射机制实现进程间通信的问题,我们请张老师谈谈这个问题。
张静盛:文件映射机制属于内存管理的一部分。在实际开发过程中,往往能够为大文件操作提供便捷、高效地操作方式。
网友问:张老师:进程通讯大多数人都说 event方法好些,方便,你认为呢?
张静盛:进程间通信的各种方法都有特定的用处,并不能说event方法就是好的,而是需要根据具体应用情况来判定。例如进程间通信有“数据”通信与“通知”通信。张前者传递的数据;后者传递的是“通知”,例如A进程通知B进程,我已经做了某件事。此时用event比较合适。而event在传数据的时候就不合适了。
网友问:还有个问题请问老师……关于管道通信,能否给举个具体的事例?
张静盛:关于管道通信:这是典型进程间数据通信的方法。管道通信的本质是内存映射,也就是说,在管道两端的两个进程,共同使用一个内存区域,内存管理器把这片内存映射到这两个进程地址空间。管道的本质只是对这个共享的内存进行了访问控制。使其适用于具体快速开发。关于管道的应用,分匿名管道和命名管道,在《Windows编程循序渐进》一书上有完整的示例。
网友问:进程和线程通信方式有什么不同?
张静盛:区别在于线程的通信比较方便,因为都处于同一个地址空间,而进程通信就不是这样了。
网友问:请问如何在两个进程间传递一个结构、或者指针?管道是不是只能传递char型的字符串?
张静盛:进程间的数据通信,传递的是数据,不能只传一个指针,因为每个进程都有自己独有的地址空间,例如A进程的指针0x12345678,它在B进程中所指向的内存就不同了。管道可以传递任何数据,对于管道来说,传的是一个字节串。无论是什么类型的数据,要传递,最后总是需要格式化成字节串。
网友问:进程通信中数据在传输过程中的保密是如何实现的?进程间通信带来的安全问题在开发中如何应对?
张静盛:进程间通信的安全问题,一般通过数据加密方式来解决。可以在传递之前实现有数据进行加密,例如使用DES对数据进行加密,然后在接收再进行解密还原。但说到底,这个安全也是有时间、范围限制的。
网友问:各种通信机制也五花八门的,请推荐几种比较好的架构或者实现方式
张静盛:通信机制确实很多。但很多都是上层应用的,经过了很多层的封装。基本的也就4 种:消息、共享内存,管道,剪贴版。在我的书中已经总结了。
进程间通信实际应用问答
网友问:可不可以帮忙讲讲进程间通讯问题,如果用sharememory怎么让另一个进程知道memory中的内容被改变了?
张静盛:这位朋友所提到的,内存改变如何通知到其他进程。共享内存,即这片内存被其他进程共同使用,反过来说,A和B进程使用同一片内存区域。那么A进程修改数据的时候,B自然就能知道。但内存映射中有个特殊的“写入时拷贝机制”,这部分暂不作展开。
网友问:如果只存在一个线程,这个线程希望每隔几个小时执行一次,例如每天的1点,5点,9点,13点,17点,21点!在不论什么时间启动该服务,只要它不在这几个时间上,就不让它运行!!想问问有没有什么好的方法?
张静盛:这位朋友所提出的实质是关于定时执行的问题。比较好的方法就是使用内存等待定时器。在《Windows编程循序渐进》一书书的第15章的第5节,有详细的介绍.
网友问:现在我想在两个进程间进行通讯,例如在其中一个进程(A)对一个全局的数组进行了修改,而在另一个进程(B)可以得到一个信号,去获取已经更新过的数组,并在此基础上做相关的工作。(我发现另一个进程B得到的总是修改A之前的数组的值)我的问题是不知如何去写两者间的通讯代码。
张静盛:关于“laokugonggao”朋友的问题。可以首先使用共享内存建立数据共享,当A进程修改数据后,使用内核事件通知B进程。这样就可以实现你预期的效果。
网友问:我刚刚接触Linux进程通信编程,请老师帮忙。我想写两个小程序 实现内容:程序a 每隔两秒发出一个在线信息给程序程序b 受到信息,终端打印“ok”。若要这两个程序之间互相通信,该怎样处理呢?
张静盛:sorry,我不熟悉linux。若在Windows上一般可以使用消息通知和内核事件通知。
网友问:有两个进程,A和B,A是基于对话框的,它还有一个模式对话框窗口C。B使用FindWindow(A)和SendMessageTimeOut向A进程的主窗口发送消息WM_COPYDATA,A在主窗口界面中能够收到此消息,我现在想如何操作能够使得消息可以流到A进程的C窗口处理中去?对B进程,它的发送和查找窗口原则不变。一直对这个问题很疑惑,希望高人指点,谢谢!
张静盛:发C窗口上发消息就可以了。
网友问:请问老师,在对UDP通信编程的时候如何才能够避免分组中的差错?有没有可能通过某种手段模拟TCP使用确认分组,超时和重传来完成差错控制?请老师指点下迷津?我正在使用UDP来模拟QQ的通信方法.发现出现很多的纰漏...所以正在寻求一个好点的解决方法
张静盛:如果这样做UDP,最后不就是TCP的形式,那么有必要这么做吗?用UDP,通常需要有个准备就是允许丢包,例如流媒体中丢包都是很正常的。如果说非要确保数据100%正确,那么一般就会用TCP了。但我不否认UDP有这个需要,当然也是可以实现的,但总体来说,实现的代价会比较大。基本做法是这样的,首先对数据进行分段标号,在接收端需要对数据进行重组,每接收到一个包就发一个响应包,其中包含ID号。
网友问:我正在使用UDP来模拟QQ的通信方法.发现出现很多的纰漏...所以正在寻求一个好点的解决方法。我开放的是一个通信端口用来数据传输.但是QQ开放一组的端口来传输数据.这个在应用上有很大的差别吗?难道能够容错吗?如果我要避免第三者在客户端和服务器之间检听我的数据?我使用多个端口来混淆数据是否可行?
张静盛:不是这么说的,QQ开端口多,主要原因是有很多引用都需要进行网络通信。多端口混淆可以作为一种方法,但个人觉得意义不大。结合逆向工程来说,这些都是小花招,起不了真正的作用。
网友问:在 RPC 建立连接后发送某种类型的格式不正确的 RPC 消息,则会导致远程计算机上与 RPC 之间的基础分布式组件对象模型 (DCOM) 接口出现问题,进而使任意代码得以执行。使用什么方法可以纠正这个错误?这个问题源于“冲攻波”【51CTO.com编者注,原文如此,疑为“冲击波”】.希望从更深的角度去看这个问题,希望老师给点建议或者方法?
张静盛:我没真正用RPC机制。但看你的描述,应该是与溢出相关,通常都是通过缓冲区溢出的。
网友问:我想问一下。两个基于对话框的应用程序 Dialog1 和Dialog2,在Dialog1中做了一个按钮用来启动Dialog2,现在启动没有问题,我想问问当Dialog2结束时如何通知Dialog1?
张静盛:如果是模态窗口的话就不用说了。非模态时,最简单的是用消息通知。