一种准确控制外部程序的方法

文档序号:6437140阅读:244来源:国知局
专利名称:一种准确控制外部程序的方法
技术领域
本发明涉及计算机软件技术,特别是涉及在Unix,Linux下方便快捷地准确控制外部程序的方法。
背景技术
在现实中经常会出现一个程序控制另一个程序的需求。比如windows下的遥控器应用软件。控制程序接收遥控器的红外信号,将其转换为相应的控制信息,然后再控制其它的外部程序。这样的过程很象一种通讯机制,也是一种进程间通讯机制。那么要如何实现这一点呢?在windows下有多种实现方法。以下是一些常用的方法。
1、共享在硬盘上建立一个文件,一个应用程序往该文件里写数据(可以不关闭文件,但必须刷新缓冲区),另一个应用程序以共享方式打开这个文件并读取其中的内容,这便是最简单的一种数据交换方式。对于网络用户而言,只要两台终端上安装的都是Win311 For Workgroup或Windows 95(或NT),则只要设置一下目录共享,映射成网络驱动器,同样可以简单地实现数据交换。但它的缺点也是显而易见的只能采取轮询的方式获得最新数据,因此效率低下,网络映射的驱动器绝对不能变动或取消,可靠性差,所以这是一种“低级”的通讯方式。
2、DDE每个Windows程序员都不会对DDE(动态数据交换)感到陌生,它是最早的基于Windows的数据交换方法,有三种方式可供选择冷连接、温连接和热连接。一般都是由客户端向服务器端发出连接申请,并且必须指明服务器端的名字和标题。在连接建立后,数据可以双向流动。典型的例子如抓图软件SnagIt,它提供了DDE接口,能够让其它应用程序来控制它。DDE是完全向后兼容的,从16位平台转到32位,源代码几乎不用修改。
DDE还有网络功能。使用过Win311 For Workgroup的人大概都还记得,它自带一个非常吸引人的小程序“Chat”,能使两台计算机通过网络实时交谈,这在当时几乎是一项创举。可是很少有人知道“Chat”使用的实际上是一种特殊的DDE,即NetDDE。它的基本工作原理仍然是DDE,但它能使一台计算机向在同一个网络中的另一台终端发消息,而不像普通DDE只能局限在同一台机器上。与其它的数据交换方式相比,DDE已不够先进,而且Microsoft也不再积极支持DDE,所以它的前景不被看好。
3、WM_COPYDATAWindows消息WM_COPYDATA功能强大,知之者却甚少。它的确切定义是一个应用程序向另一个应用程序传递数据时所发出的消息。众所周知,Windows在很大程度上依赖于消息机制,那么为什么不把数据放在消息中一起发送出去呢?这样,只要调用SendMessage(),以对方窗体的句柄作为第一个参数,以含有指向实际数据的指针结构的地址作为第二个参数,就可以把整个数据块当作消息发向另一个应用程序。也许有的程序员会说,一个自定义的消息同样可以完成这样的工作。他只说对了一半,自定义消息的确可以发送到其它的应用程序上去,但其原始数据所在的内存区只有在发送过程中才是合法的,若在其它模块中存取该内存区就会导致“AccessViolation”。而使用WM_COPYDATA则不存在这个问题,因为Windows本身会替你处理这一切。深入钻研下去,就会发现它其实是先创建了一个文件映射的对象,将发送方的原始数据先拷贝至映射文件,然后再在接收方对这个映射文件打开一个“视图”。WM_COPYDATA的不足之处在于必须要有一个窗体来接收消息和数据,缺乏灵活性,数据在使用之前先得拷贝到一个映射文件,造成资源浪费。
4、NetBIOS
从20世纪80年代开始,NetBIOS就是开发Client/Server类程序的标准接口。而当时其它的解决方案几乎都是从UNIX系统上发展而来的。当然,对于今天的用户而言,NetBIOS已不是唯一的选择,他们可以从各种方案中择优选取。在Windows 95和NT平台上,可以通过API函数Netbios()来调用NetBIOS功能。
NetBIOS兼容以下几种低层协议NetBEUI协议(NBF)、NWLinkNetBIOS(NWNBlink)、NetBIOS over TCP/IP(NetBT)。NetBIOS的优点是速度较快,缺点是可靠性较差。
5、标准的Sockets和WinSockSockets是15年前在UNIX系统上提出来的,一开始主要是用于本地通讯,但很快就应用在Client/Server体系上了。它的内核很简单你可以将一个Socket看作是一个双向的节点,一个应用程序可以通过它先与另一个程序建立连接(建立在一个双方都认可的端上,以便于区分同时运行的几个通讯线程),然后就可以彼此交换数据了。微软公司在其基础上创建了WinSock,专门用于Windows接口,与Socket完全兼容。近年来基于TCP/IP协议的网络大行其道,Socket也随之获得了更加广泛的应用。
如今,Sockets已在Internet上获得了最广泛的应用,主要是因为它的可移植性好Socket应用程序无论在任何平台间都能互相进行通讯(不管是PC机还是Macintosh,也不管是Windows平台还是UNIX平台)。而最新推出的WinSock2.0,已不仅仅只基于TCP/IP协议,还可基于其它几种传输协议(如IPX)。Socket的缺陷是它工作在通讯的低层,所以实现起来较为复杂(如果是Win95或NT平台,则不存在这个问题,微软公司提供了相应的控件)。但是,如果要在多个平台间互相通讯,则Socket是不二之选。
6、Mailslot和PipeMailslot和Pipe有很多相同点,即都是高层的、基于内存的通讯系统。Mailslot由Server端创建,代码如下myMailslot=CreateMailslot(pSlotName,0,MAILSLOT_WAIT_FOREVER,NULL);然后,Client端就可以像打开文件一样打开这个Mailslot,再通过API函数WriteFile()来将数据写入到消息队列中。
与此相类似,Pipe也是由Server端创建的,代码如下pipe=CreateNamedPipe(pPipeName,PIPE_ACCESS_DUPLEX,PIPE_TYPE_MESSAGE|PIPE_READMODE_MESSAGE|PIPE_WAIT,PIPE_UNLIMITED_INSTANCES,BUFSIZE,BUFSIZE,20000,NULL);接着,Client端就可以通过一般的文件API读写数据,代码如下pipe=CreateFile(pPipeName,GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,NULL);success=WriteFile(pipe,pMessage,strlen(pMessage)+1,& bytesWritten,NULL);Pipe分两种,即命名Pipe和匿名Pipe。匿名Pipe是以句柄而不是以名字来进行标识的,因而也就限制了它只能在同一台机器上通讯,而不能应用于网络。命名Pipe则提供了以名字来进行标识,所以能在网络上的其它任何地方打开它。需要注意的是命名Pipe只能在Win NT而不是Win 95上创建(即Server端),Client端则可以是任意平台。
Pipe既可以单向通讯也可以双向通讯,Mailslot则只能单向通讯。Client端可以发送消息给mailslot,但不能接收消息;如果你想要接收消息,则只能创建一个新的mailslot。但mailslot有一个很大的优点它支持数据广播。也就是说,若Client端发送一条消息,则整个网络中的同名对象都能收到。这是因为mailslot的名字的作用域只是在本台机器上,所以可在不同机器上创建同名的mailslot,当Client端发来消息时则每一台机上的mailslot都得到了该消息的一份拷贝,并在本机上作出相应的反应。Mailslot的最大缺陷是不可靠,因为它的数据是以数据报格式来传送的,网络错误或负荷过重都会导致数据丢失。
Pipe虽然较为可靠,但它不能广播。所以,如果不需要进行广播,则Pipe是更好的选择。选择Mailslot,则要对此后遇到的麻烦有充分的准备。
7、多剪贴板(Clipboard)Windows的剪贴板的出现就是为了实现应用程序间的互相数据交换。Windows提供了一系列的API函数来让应用程序安全地打开剪贴板,读写其中的数据。
剪贴板的缺陷也是显而易见的当有新的数据放在剪贴板上时,则先前的数据就会被冲掉,而在Windows中用到剪贴板的时候又实在太多了,所以这种方式用于程序间的通讯显然不够安全。
8、COM和DCOM公共对象模式(COM)是一种协议,它建立了一个软件模块同另一个软件模块之间的连接,然后将其描述出来。当这种连接建立起来之后,则两个模块之间就可以通过称为“接口”的机制来进行通讯。COM可以用不同的语言(VB、VC、Delphi)进行编制,又能被其它语言编写的程序所使用,并且不用理睬通讯双方实际所处的位置(是在同一台机上,还是在同一个网络上的不同机上)。事实上,Internet上有大量的COM控件可供人们下载使用,其中有相当一部分就是用于应用程序间的相互通讯(甚至是Internet程序间的通讯),硬盘上能够看到的大量的。ocx文件其实就是一种COM。
COM对象为外部调用提供了一个标准的界面,COM Client通过创建COMserver的一个实例获得指针,转向所需的函数定义处并执行相应的程序。讲得通俗一点,也就是先正确定义好COM对象的属性(Property),再执行相应的方法(Method)。
DCOM(分布式公共对象模式)是COM在网络上的一种扩展,它通过把分布式对象间的通讯变成一个实体来实现通讯。
COM如今被微软公司大力提倡,最著名的有OLE、ActiveX、DirectX和Win95、WinNT的外壳。由于微软公司目前在软件业处于霸主地位,所以COM很有可能成为将来的业界标准,其前途也较为看好。但COM的庞大也会使一些经验丰富的程序员望而却步,他们宁可自己多写一些代码以使整个程序更为简洁、有效而不愿使用COM。
以上这些通讯方式都可以用来实现进程间的相互控制。但是都有一定的局限性。比如拿wi ndows消息传送来举例,为了说明这种方法,先来了解一下Windows消息驱动的工作机制。Windows的驱动方式是事件驱动,就是不由事件的顺序来控制,而是由事件的发生来控制,所有的事件都是无序的,作为一个程序员,在编写程序时,并不知道用户先按哪个按纽,也不知道程序先触发哪个消息。程序员的任务就是对正在开发的应用程序要发出或要接收的消息进行排序和管理。事件驱动程序设计是密切围绕消息的产生与处理而展开的,一条消息是关于发生的事件的消息。就是说当你按下界面中的一个按钮,选择一个菜单,选择一个列表的时候都是向windows发出了一个消息,windows会把这个消息正确分配给相应的窗口函数。那么如果要达到控制其它程序的目的,只要能模拟出控制操作相应的消息即可。但是这样的做法的缺点是,对于每一个外部程序的控制必须先了解他的消息ID,虽然可以通过一些消息截获的工具软件获得这一信息ID,但还是很麻烦,因为消息ID对于用户是不可见的。这个问题造成程序很难做得通用。

发明内容
本发明要解决的技术问题是提出一种准确控制外部程序的方法,实现在Unix,Linux下方便快捷地控制外部程序。
本发明的实现方法如下步骤一、由控制程序的一个实例进程一,创建一个管道;步骤二、进程一用Linux的fork()函数创建一个子进程进程二;这个子进程会获得进程一的数据空间,堆和栈的复制品;步骤三、在进程一和进程二之间创建两个这样的共享管道,以实现两个进程间的双向数据读写;步骤四、根据数据流的方向,分别关闭所述两个进程共享管道的读端或写端,仅保留一个读端和写端;步骤五、将进程二的读写端连接到标准输入输出设备上;步骤六、加载需要控制的外部程序到子进程上,以实现控制程序对外部程序的完全控制。
采用本发明,能在Unix,Linux下方便快捷的实现控制外部程序。就可以大量的复用目前已有的程序,提高代码复用性,节省开发时间,而不用重新编写,节省了大量的开发成本;由于使用的是久经考验的程序,提高系统的可靠性。


图1是本发明所述方法实现向外部程序发送命令的流程;图2是本发明所述方法实现从外部程序读出输出结果的流程;图3是管道的示意图;图4是创建子进程后的管道;图5是从父进程到子进程的管道;图6是从子进程到父进程的管道。
具体实施例方式
Unix,Linux下实现进程间通讯的方法主要有以下几种,管道、消息队列、信号量和共享存储。由于管道是极少数可以在几乎所有的Unix,Linux下都支持的通讯方式,所以用这种方法实现移植性很好。因此本发明采用管道来达到控制的目的。
本发明所述方法的基本步骤如下所述首先,控制程序的一个实例进程一创建一个管道。
进程一用Linux的fork()函数创建一个子进程进程二,由于这个子进程会获得其父进程即进程一的数据空间,堆和栈的复制品,但管道本身不会被复制,因此这个子进程就可以和父进程进程一共享同一个管道。这个管道在每一个进程处都有一个读端和写端。根据数据流的方向分别关闭这两个进程共享管道的读端或写端。
仅留下一个读端和写端。这样数据就可以从一个进程中的写端流向另一个进程的读端。当需要向子进程写数据的时候就关闭父进程的读端和子进程的写端。反之需要从子进程读数据的时候就关闭父进程的写端和子进程的读端。
在父进程和子进程之间创建两个这样的共享管道,就可以实现两个进程间的双向数据读写。
连接子进程这边的读写端到标准输入输出设备上,那么父进程流向子进程的数据在子进程看来就象从键盘输入的一样,而子进程输出到标准输出设备(一般是屏幕)的数据,父进程可以完全的从管道的读端获取。
加载需要控制的外部程序到子进程上,就可以实现控制程序对外部程序的完全控制。
以下结合附图以及实施例进一步说明本发明的基本思想。
如图1所示,这是本发明所述方法的一个具体实施例,可以实现控制程序向外部程序发送命令。
第一步,创建父进程的一个管道;第二步,创建一个子进程,子进程会共享父进程的管道;第三步,关闭子进程的写管道;第四步,将子进程的读管道连接到标准输入,利用这个子进程加载要控制的外部程序;第五步,关闭父进程的读管道;第六步,从父进程的写管道写入命令,对于子进程程序来说就和接收键盘输入一样,从而实现控制外部程序的目的。
如图2所示,这是本发明所述方法的另一个具体实施例,可以实现控制外部程序,即从外部程序读出输出结果。具体步骤如下第一步,创建一个管道;第二步,创建一个子进程,子进程会共享父进程的管道;第三步,关闭子进程的读管道;第四步,将子进程的写管道连接到标准输出,利用这个子进程执行要控制的外部程序;第五步,关闭父进程的写管道;第六步,从父进程的读管道读入外部程序的输出,父进程可以根据输出来改变发送的命令流,从而实现控制外部程序的目的。
图3是管道的示意图,本发明中关于Linux下管道的实质其实是驻留在内核中的在内部表示的一个合法索引节点,并且不在任何物理文件系统的范围之内。对管道的读写其实就是对内核中这个节点的读写,利用这个特性,就可以实现控制外部程序。
图4是创建子进程后的管道;可以看出,子进程会共享父进程创建的管道,每一个进程都分别有一个该管道的读端口和一个写端口。
图5是从父进程到子进程的管道;如果关闭父进程对于这个管道的读端口和子进程对于这个管道的写端口,就可以形成数据只能从父进程流向子进程的管道。再把子进程的标准输入端口连接到这个管道在子进程那边的读端口,那么从父端口写入的数据就如同从键盘向子进程输入数据一样,从而实现模拟键盘对子进程的控制。
图6是从子进程到父进程的管道。如果关闭父进程对于这个管道的写端口和子进程对于这个管道的读端口。就可以形成数据只能从子进程流向父进程的管道。再把子进程的标准输出端口连接到这个管道在子进程那边的写端口,那么从子进程输出到屏幕的数据就可以完全的从父进程的读端口读出,从而使父进程可以得到子进程的所有输出反馈。
最后所应说明的是以上实施例仅用以说明而非限制本发明的技术方案,尽管参照上述实施例对本发明进行了详细说明,本领域的普通技术人员应当理解依然可以对本发明进行修改或者等同替换,而不脱离本发明的精神和范围的任何修改或局部替换,其均应涵盖在本发明的权利要求范围当中。
权利要求
1.一种准确控制外部程序的方法,其特征在于,包括如下步骤步骤一、由控制程序的一个实例进程一,创建一个管道;步骤二、进程一创建一个子进程进程二;步骤三、在进程一和进程二之间创建两个这样的共享管道,以实现两个进程间的双向数据读写;步骤四、根据数据流的方向,分别关闭所述两个进程共享管道的读端或写端,仅保留一个读端和写端;步骤五、将进程二的读写端连接到标准输入输出设备上;步骤六、加载需要控制的外部程序到子进程上,以实现控制程序对外部程序的完全控制。
2.根据权利要求1所述的准确控制外部程序的方法,其特征在于,向外部程序发送命令时,所述步骤四中包括关闭子进程的写管道;将子进程的读管道连接到标准输入,利用这个子进程加载要控制的外部程序;关闭父进程的读管道;从父进程的写管道写入命令。
3.根据权利要求1所述的准确控制外部程序的方法,其特征在于,从外部程序读出输出结果时,所述步骤四中包括关闭子进程的读管道;将子进程的写管道连接到标准输出,利用这个子进程执行要控制的外部程序;关闭父进程的写管道;从父进程的读管道读入外部程序的输出。
4.根据权利要求1、2、3之一所述的准确控制外部程序的方法,其特征在于,所述步骤二中进程一用Linux的fork()函数创建一个子进程进程二;所述子进程获得进程一的数据空间,堆和栈的复制品。
5.根据权利要求1、2、3之一所述的准确控制外部程序的方法,其特征在于,所述管道为驻留在内核中的在内部表示的一个合法索引节点。
全文摘要
本发明公开了一种准确控制外部程序的方法,包括如下步骤步骤一、由控制程序的一个实例进程一,创建一个管道;步骤二、进程一创建一个子进程进程二;步骤三、在进程一和进程二之间创建两个这样的共享管道,以实现两个进程间的双向数据读写;步骤四、根据数据流的方向,分别关闭所述两个进程共享管道的读端或写端,仅保留一个读端和写端;步骤五、将进程二的读写端连接到标准输入输出设备上;步骤六、加载需要控制的外部程序到子进程上,以实现控制程序对外部程序的完全控制。采用本发明,能在Unix,Linux下方便快捷的实现控制外部程序,就可以大量的复用目前已有的程序,提高代码复用性,节省开发时间,而不用重新编写,节省了大量的开发成本。
文档编号G06F9/52GK1516010SQ0310000
公开日2004年7月28日 申请日期2003年1月2日 优先权日2003年1月2日
发明者邵苏毅, 陆宽, 柯妍 申请人:联想(北京)有限公司
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1