在16位Windows时代,DLL内存的处理和32位Win32的处理时不同的。在16位的DLL中,可以在不同应用程序之间共享全局内存。换句话说,如果在16为DLL中声明了一个全局变量,任何调用该DLL的引用程序都可以修改这个变量,这种修改回反映到其他应用程序中。
在Win32中不存在这种DLL的全局数据共享。由于每个应用程序进程把DLL映射到自己的地址空间中,DLL的数据也映射到了应用程序进程空间中。所以每个应用程序具有自己的DLL数据实例。一个应用程序对DLL中全局数据的修改不会影响到其他应用程序。
那如何实现在Win32下DLL数据共享呢,这是可以用内存映射文件来储存共享数据。内存映像文件可以映射一个文件,一个文件中的指定区域或者指定的内存块,其中的数据就可以用内存读写指令来直接访问,而不必频繁的调用I/O系统函数,从而提高了文件存取速度和效率。
映像文件的另一个重要应用就是用来支持永久命名的共享内存。要在两个应用程序之间共享内存,可以在一个应用程序中创建一个文件并映射之,然后另一个程序可以通过打开和映射该文件,并把它作为自己进程的内存来使用。
创建映像文件
CreateFileMapping( hFile: THandle; lpFileMappingAttributes: PSecurityAttributes; flProtect, dwMaximumSizeHigh, dwMaximumSizeLow: DWORD; lpName: PChar ): THandle;
- hFile:是调用FileOpen或FileCreate函数后返回的文件句柄。如果不是共享文件而是共享内存区域,在这里需要设为$FFFFFFFF(DWord(-1)).
- lpFileMappingAttributes参数是文件映像的安全属性结构(一般设为nil)。
- flProtect 参数是文件的保护类型(PAGE_READ为可读 PAGE_WRITE为可写 PAGE_READWRITE为可读写)
- dwMaximumSizeHigh 参数用于指定文件映像的大小的高32位。
- dwMaximumSizeLow 参数用于指定文件映像的大小的低32位。
- lpName 参数用于指定映像名。
如果函数调用成功,将返回文件映像的句柄。
打开映像文件
OpenFileMapping( dwDesiredAccess: DWORD; bInheritHandle: BOOL; lpName: PChar ): THandle;
- dwDesiredAccess 用于指定访问数据的模式(FILE_MAP_READ为可读 FILE_MAP_WRITE为可写 FILE_MAP_ALL_ACCESS为可读写)
- bInheritHandle 参数指定OpenFileMapping 函数返回的句柄在以后新建的子进程中是否得到继承。
- lpName 参数用于指定映像名。
如果函数调用成功,将返回文件映像的句柄。
映射到本地进程
MapViewOfFile( hFileMappingObject: THandle; dwDesiredAccess: DWORD; dwFileOffsetHigh,dwFileOffsetLow,dwNumberOfBytesToMap:DWORD ): Pointer;
- hFileMappingObject 参数通过CreateFileMapping 或 OpenFileMapping返回的文件映像句柄。
- dwDesiredAccess 用于指定访问数据的模式(FILE_MAP_READ为可读 FILE_MAP_WRITE为可写 FILE_MAP_ALL_ACCESS为可读写)
- dwFileOffsetHigh 参数用于指定数据在映像文件中的起始位置的高32为
- dwFileOffsetLow 参数用于指定数据在映像文件中的起始位置的低32位。
- dwNumberOfBytesToMap 参数用于指定需要映射的字节数,设为0表示文件或内存区域的全部。
如果函数调用成功将返回数据映射的起始地址,这是本进程中可以直接访问的内存地址指针。
关闭内存映射
UnmapViewOfFile( lpBaseAddress: Pointer ): BOOL;
- lpBaseAddress为MapViewoffFile返回的内存指针。