探讨下在Delphi里面进程之间的数据共享
Posted 箜喒
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了探讨下在Delphi里面进程之间的数据共享相关的知识,希望对你有一定的参考价值。
进程是一个具有一定独立功能的程序关于某个数据集合的一次运行活动。它是操作系统动态执行的基本单元,在传统的操作系统中,进程既是基本的分配单元,也是基本的执行单元。现在小编就和大家来探讨一下在Delphi里面进程之间的数据共享吧。
一、动态链接库
DLL(即动态链接库),是Dynamic Link Library的缩写形式,它是一个包含可由多个程序同时使用的代码和数据的库。除此之外,它还是实现代码重用的重要手段,创建Windows应用程序。那么问题就来了?当我们需要在进程之间共享数据的时候,应该如何做才可以最简单最快速的将其实现出来呢?如果大家还不知道方法的话,那就跟着小编一起来学习吧。
不知道大家是否知道,在32位应用系统里面,每一个应用程序都会把DLL映射到自己的地址空间里面,同一时间DLL里面的数据也就随之被映射(两个元素的集之间元素相互"对应"的关系)了。这样子操作的话,每一个应用程序都会拥有属于有自己的一个数据实例。当然啦,我们在一个应用程序里面修改DLL中的全局变量,这样子是并不会影响到其它应用程序的。大家是不是觉得,DLL的使用好像和我们要实现的目的有点相背离呢?其实小编也是这样认为,那么怎样才可以真正的实现到我们想要的东西呢?大家想到方法了吗?如果还没有,不妨尝试一下小编的建议吧。在这里,小编要为大家介绍一种技术,那就是内存映射文件,这是一种较为特殊的方法哟,到底有多特殊,现在就来看一看吧。
二、内存映射文件
内存映射文件,是由一个文件到一块内存的映射,内存映射文件与虚拟内存有些类似。在内存映射文件中,为用户提供了一种非常好使的方法。这种方法就是在WIN32系统的地址空间里面,将一块内存区域保留出来,然后物理存储就可以向其中进行提交。另外一个方面,内存映射文件不仅仅只是WIN32的页面文件,还可以是一个磁盘文件。小编认为这两者之中,前者要比后者好用,因为这样子就意味着大家可以像访问一个磁盘文件那样访问内存里面的一个区域了。然而我们再也不需要使用创建一个临时文件,当它用完了以后还得需要将其删除。在WIN32里面就拥有着自己的管理页面调度文件,当大家不需要页面调度文件的时候,系统就会自动将全部有关的区域释放。
三、实现方法
那么接下来小编就向大家演示一下实现方法吧,在这一段编程代码中小编还特意写了注释,希望这对大家有所帮助。另外一个方面,这一个示范例子是在DELPHI6里面编译通过,所以大家一定要注意咯。编程代码如图所示:
- library Project1;
- uses
- shareMem,
- windows,
- SysUtils,
- Classes;
- const
- MFileName: Pchar = ’ShareData’;
- //定义一个记录类型,你所需要共享的数据就保存在这里。
- //当在进程中调用GetDllData时,进程中也应该定义一个与这个一样的记录类型。
- type
- PGlobalDllData = ^TGlobalDllData;
- TGlobalDllData = record
- s: string[50];
- i: integer;
- end;
- var
- GlobalData: PGlobalDllData; //这是一个全局变量,指向创建的内存映射文件。
- MapHandle: THandle;
- //给外部进程调用的过程,当外部进程调用这个过程后,形参AGlobalData就指向了我
//们创建的内存映射文件. 我们可以创建两个进程, 同时调用这个过程, 那么在其中一个进 //程中修改数据后, 在另外一个进程中既可反应出来, 实现了我们需要的共享. - procedure GetDllData(var AGlobalData: PGlobalDllData);stdcall; begin
- AGlobalData := GlobalData;
- end;
- procedure OpenThisData;
- var
- size: integer;
- begin
- size := sizeof(TGlobalDllData);
- //创建一个内存文件映射对象,MfileName保存的值就是该对象的名字。
- mapHandle := CreateFileMapping(Dword(-1), nil, page_readWrite, 0, size, MFileName);
- if mapHandle = 0 then
- RaiseLastWin32Error;
- //把文件的视图映射到调用进程的地址空间,该函数的返回值就是该对象的首地址。注//意,这是调用进程的地址,两个应用程序调用该DLL,返回值是不一样的。
- GlobalData := MapViewOfFile(mapHandle, File_map_all_Access, 0, 0, size);
- Globaldata^.s := ’TEST’;
- GlobalData^.i := 5;
- if GlobalData = nil then
- begin
- CloseHandle(MapHandle);
- RaiseLastWin32Error;
- end;
- end;
- //DLL从进程中分离出来时,应该释放相应的空间
- procedure CloseThisData;
- begin
- unmapViewOfFile(GlobalData);
- closeHandle(MapHandle);
- end;
- procedure DllEntryPoint(dwReason: DWord);
- begin
- case dwReason of
- Dll_Process_Attach: OpenThisData; //调用DLL时传入的参数,由系统自动传入
- Dll_Process_Detach: CloseThisData; //释放DLL时传入的参数,系统自动传入。
- end;
- end;
- {$R *.res}
- exports
- GetDllData; //外部应用程序调用的就是这个过程。
- begin
- DllProc := @DllEntryPoint; //该变量是一个全局变量,由它来指定DLL的入口及出 //口函数。
- DllEntryPoint(Dll_Process_Attach);
- end.
小编结语:
通过这篇编程语言教程,不知道大家是否已经学会了在Delphi里面进程之间的数据共享呢?在这篇教程中,主要就是向大家介绍一下数据共享。希望这对大家有所帮助。
以上是关于探讨下在Delphi里面进程之间的数据共享的主要内容,如果未能解决你的问题,请参考以下文章
11.python并发入门(part10 多进程之间实现通信,以及进程之间的数据共享)