当前位置:文档之家› 基于内存映射文件的数据共享技术的应用与研究

基于内存映射文件的数据共享技术的应用与研究


exit(1);
}
if (GetLastError() == ERROR_ALREADY_EXISTS)
{
MessageBox(NULL,"ALREADY EXITS","Init",MB_OK);
}
if ( (lpBase = (LPVOID) MapViewOfFile( hMap,
FILE_MAP_ALL_ACCESS ,
下面简单描述笔者在开发过程中对该技术的使用。
一个输入法经过编译后是一个以.ime 作为扩展名的动态链接库,所以输入法的初始化 需要遵循动态链接库的设计。在输入法的接口函数即动态链接库的入口函数内,接受到消息
DLL_PROCESS_ATTCH 时,完成输入法的加载及共享内存空间的初始化;在接受到消息 DLL_PROCESS_DETATCH 时,完成输入法的卸载及共享内存空间的释放。下面代码简单显 示了上述过程。
的语言模型与大量的规则,即“知识”,这一切与简单的字输入相比,需要占用更多的系统
资源。例如,基于理解的智能输入软件需要汉语语法知识;基于语用统计的智能输入软件需
要语用统计数据;基于模板匹配的智能输入软件需要模板词库与句法规则库,等等。研究发
现,当前典型的输入法占用的内存大小在 6M 左右。同时,鉴于 win98/2000/NT 环境下应用 程序间不再共享输入法实例,如果每生成一个输入法实例,都要占用固定数量的系统资源,
…….
UnmapViewOfFile(lpBase);
CloseHandle(hMap);
…….
}
2.2 使用内存映射文件时注意的问题
当开发人员使用内存映射文件与其他进程共享数据时,某些情况下需要使用 MapViewOfFileEx 函数。例如,当两个或多个应用程序需要共享包含指向其他数据结构的一 组数据结构时,可能需要在某个特定地址上的内存映射文件。以链表为例。在链表中,若要 遍历该链表,必须知道第一个元素的地址,然后参考包含下一个元素地址的元素成员。当使 用内存映射文件时,这可能成为一个问题。
由于该技术需要开发人员对 windows 虚拟内存管理机制有深入地了解,因此,本文对 该技术的原理、实现及应用进行了详细的阐述。
1 内存映射文件的原理 1.1 进程的虚拟地址空间
win32 环境下,每个进程拥有 4GB 的私有虚拟地址空间。但这并不代表进程真正拥有 4GB 的实际物理内存,而只是操作系统利用 CPU 的内存分配功能提供的虚拟地址空间。一 般情况下,绝大部分虚拟地址空间并没有物理内存与之对应,在真正可以使用该地址空间之 前,需要由操作系统提供实际的物理内存,这一过程称为提交(保留)。在不同的情况下, 系统提交的物理内存是不同的,可能来自 RAM,也可能是由物理磁盘模拟虚拟内存。
BOOL WINAPI DllMain (HINSTANCE hInstDLL, DWORD
dwFunction,
LPVOID
lpNot)
{
switch(dwFunction)
{
case DLL_PROCESS_ATTACH://load ime
…….
HANDLE hMap;
LPVOID lpBase=NULL;
另一方面,win9x/2000/NT 平台下输入法的一个特点就是多个应用程序间不再共享一个 输入法实例,而是每个应用程序都拥有自己的一个独立的输入法实例,所以必须实现在同一 个输入法的多个实例间共享数据,以降低系统的资源耗费。鉴于现代输入法的高智能性对大 量“知识”即统计数据与规则的需求及内存映射文件技术的特点,笔者在开发“INSUN 拼 音语句输入法”的过程中,运用该技术取得了令人满意的效果。
对于该问题有两种解决方法。第一个方法,当第二个进程将包含链表的内存映射文件 映射到它自己的地址空间中去时,调用 MapViewOfFileEx 函数。当然,该方法需要第二个 进程知道第一个进程建立链表时将文件映射到什么地方。可以将地址以硬编码放入两个应用 程序,或者一个进程可以通知另一个进程使用进程间通信的方法,比如将消息发送到窗口。 第二个方法是创建链表的进程将下一个节点所在的地址中的位移存放在每个节点中。这要求 应用程序将该位移添加给内存映射文件的基地址,以便访问每个节点。这种方法并不高明, 因为它的运行速度可能比较慢,它会使程序便大。
如果一个进程建立了内存映射文件中的链表,然后与另一个进程共享该文件,那么另 一个进程可能将文件映射到它的地址空间的一个完全不同的位置上。当第二个进程试图遍历 该链表时,它查看链表的第一个元素,检索下一个元素的内存地址,然后设法引用下一个元 素。然而,第一个节点的下一个元素的地址并不是第二个进程需要查找的地址。
1.2 内存映射文件的实现原理
从系统实现的角度看,该技术主要基于 win32 的虚拟内存管理机制。由于 win32 是一 个页式虚拟内存操作系统,内存映射文件技术成为内存管理系统的一个重要组成部分。我们 知道,在较老的操作系统中,物理存储器被视为计算机拥有的 RAM 容量,但是,现代操作 系统与 CPU 技术的发展,使得整个磁盘空间就像内存 RAM 一样。磁盘上的文件称为页文 件,它包含了可供所有进程使用的虚拟内存。实际上若用户同时运行多个应用程序,页文件
从使用者的角度看,数据共享方法是通过让两个或多个进程映射同一文件映射对象的 视图来实现的,这意味着他们将共享磁盘上同一文件或者物理存储器的同一页面。因此,当 一个进程将数据写入一个共享文件映射对象的视图时,其它进程可以立即看到它们视图中的 数据变更情况。通过上述操作,用户操作文件就能够达到操作内存一样的效率,多个进程操 作该映射文件实现进程间内存一级的高速数据交互。
不会像用户想象的那样变得很大。如果情况如此,那么系统将耗费很长时间进行页面的换入 换出工作。相反,当启动一个应用程序时,系统将打开该应用程序的.exe 文件,确定该应用 程序的代码与数据大小,然后系统保留一个地址空间的区域,并指明与该区域相关联的物理 存储器是.exe 文件本身,即系统并不是从页文件中分配地址空间,而是将.exe 文件的实际内 容映像用作程序的保留地址空间区域,如此,使得应用程序的加载非常迅速,并且不增加页 文件的大小。当磁盘上一个程序的文件映像(.exe 文件或 DLL 文件)被用作与进程地址空 间区域相关联的物理存储器时,称之为内存映射文件。
用函数 PVOID MapViewOfFile(HANDLE hFileMappingObject,…..)。将上一步骤返回的文件 映射内核对象传递给 hFileMappingObject;通过该函数的调用,系统为文件的数据保留一个 地址空间区域,并将文件的数据作为映射到该区域的物理存储器进行提交;函数调用成功返 回该地址空间区域的基地址,利用该函数返回的指针即可实现对该空间的访问。
当完成对内存映射文件的使用时,必须执行下面步骤将它清除。 1)调用 UnmapViewOfFile 从进程地址空间中撤销文件映射内核对象的映像。 2)调用 CloseHandle 关闭文件映射内核对象与文件内核对象,防止资源泄漏。
2 内存映射文件的应用 2.1 内存映射文件的应用实例
汉字输入从最初的字输入发展到目前的语句级输入,智能性愈来愈高,自然需要更恰当
1.3 内存映射文件的使用
如果使用内存映射文件,必须执行下列操作步骤: 1)创建或打开一个文件内核对象,该对象用于标志磁盘上你想用作内存映射文件的文 件。 2)创建一个文件映射内核对象,通知系统该文件的大小和你打算如何访问该文件。该 步骤需要调用函数 HANDLE CreateFileMapping(HANDLE hFile,…)。如果创建磁盘文件支持 的内存映射文件,须将上一步骤返回的文件内核对象句柄传递给 hFile;如果创建系统的页 文 件 支 持 的 内 存 映 射 文 件 ( 进 程 间 共 享 内 存 ), 可 以 不 必 调 用 CreateFile , 而 直 接 将 INVALID_HANDLE_VALUE 传递给 hFile 即可;其它相应参数分别设定文件映射内核对象 的安全属性、叶面保护属性、页面的大小、文件映射内核对象的名字。通过上述调用,获得 文件映射内核对象句柄。 3)让系统将文件映射对象的全部或一部分映射到你的进程地址空间中。该步骤需要调
Abstract: this paper analyzes the implementation principles of memory mapping file technology under win32 environment and gives its application in the development of input method software. Key Words: virtual memory, memory mapping, input method, shared-memory
if((hMap=CreateFileMapping( INVALID_HANDLE_VALUE,
NULL,
PAGE_READWRITE ,
0,
4*1024*1024,
_T("MMShare"))) == NULL) //create or open an
kernel object
{
MessageBox(NULL,"FILE MAPPING CREATE FAIL","Init",MB_OK);
Process1 virtual memory
Physical memory
File on disk
File mapping
File e view2 Process2 virtual memory
File view2
图示:内存映射文件原理示意图
0,
0,
0)) == NULL) {
MessageBox(NULL,"FILEVIEW CREATE FAIL","Init",MB_OK);
相关主题