转自:http://www.zxbc.cn/html/20080524/51094.html
与虚拟内存一样,内存映射文件可以用来保留一个地址空间的区域,一旦该文件被映射,就可以访问它,就像整个文件已经加载内存一样。
  内存映射文件可以用于3个不同的目的:
   1. 系统使用内存映射文件,以便加载和执行exe 和dll文件,这可以大大节省页文件空间和应用程序启动运行所需的时间。
   2.可以使用内存映射文件来访问磁盘上的数据文件,这使你可以不必对文件执行I/O操作,并且可以不必对文件内容进行缓存。
   3.可以使用内存映射文件,使同一台计算机上运行的多个进程能够相互之间共享数据,Windows确实提供了其他一些方法,以便在进程之间进行数据通信,但是这些方法都是使用内存映射文件来实现的,这使得内存映射文件成为单个计算机上多个进程互相进行同行的最有效的方法。
一.内存映射文件的函数包括
		
				CreateFileMapping , OpenFileMapping, MapViewOfFile, UnmapViewOfFile 
				
						和
				
				FlushViewOfFile
				
						。
						
								
								
						
				
		
		
				
						用法如下:
						
								
								
						
				
		
		
				1
				
						.
				
				HANDLE CreateFileMapping(
		
		
				
						  HANDLE                  hFile,              // 
				
						一个文件句柄
						
								
								
						
				
		
		
				
						  LPSECURITY_ATTRIBUTE  lpAttributes,         // 
				
						定义内存映射文件对象是否可以被承
						
								
								
						
				
		
		
				
						  DWORD                   flProtect,           // 
				
						该内存映射文件的保护类型
						
								
								
						
				
		
		
				
						  DWORD                   dwMaximumSizeHigh,// 
				
						内存映射文件的长度
						
								
								
						
				
		
		
				
						  DWORD                   dwMaximumSizeLow, //
		
		
				
						  LPCTSTR                  lpName             // 
				
						内存映射文件的名字
						
								
								
						
				
		
		
				)
		
		
				hFile       
				
						指定要映射的文件的句柄,如果这是一个已经打开的文件的句柄(
				
				CreateFile
				
						函数的返回值),那么将建立这个文件的内存映射文件,如果这个参数为
				
				-1
				
						,则建立共享内存。
						
								
								
						
				
		
		
				lpAttribute  
				
						安全属性,一般设为
				
				NULL
		
		
				flProtect    
				
						指定映射文件的保护类型,它的取值可以是
				
				PAGE_READONLY
				
						(内存页面只读)
				
				
				
				
						或
				
				PAGE_READWRITE
				
						(内存页面可读写)。
						
								
								
						
				
		
		
				dwMaximumSizeHigh 
				
						和
				
				dwMaximumSizeLow
				
						参数组合指定了一个
				
				64
				
						位的内存映射文件的长度。一种简单的方法是将这两个参数全部设置为
				
				0
				
						,那么内存映射文件的大小将与磁盘文件大小一致。 
				
		
		
				2
				
						.
				
				HANDLE OpenFileMapping(
		
		
				
						      DWORD               dwDesiredAccess,    // 
				
						指定保护类型
						
								
								
						
				
		
		
				
						      BOOL                  bIsInheritHandle,     // 
				
						返回的句柄是否可以被继承
						
								
								
						
				
		
		
				
						      LPCSTR                lpName             // 
				
						创建对象时使用的名字
						
								
								
						
				
		
		
				
						     
				
				
						)
						
								
								
						
				
		
		
				
						如果创建的是共享内存,其他进程不能再使用
				
				CreateFileMapping
				
						函数去创建同名的内存映射文件对象,而要使用
				
				OpenFileMapping
				
						函数打开已创建好的对象。
						
								
								
						
				
		
		
				dwDesiredAcess   
				
						指定保护类型有
				
				FILE_MAP_WRITE 
				
						或
				
				FILE_MAP_READ
		
		
				3
				
						.
				
				LPVOID  MapViewOfFile(
		
		
				
						      HANDLE  hFileMappingObject,    // 
				
						前两个函数返回的内存映射文件的句柄
						
								
								
						
				
		
		
				
						      DWORD  dwDesiredAcess,      // 
				
						保护类型
				
				FILE_MAP_READ ,FILE_MAP_WRITE
		
		
				
						      DWORD  dwFileOffsetHight,     // 
				
						从文件的那个地址开始映射
						
								
								
						
				
		
		
				
						      DWORD  dwFileOffsetLow,
		
		
				
						      SIZE_T   dwNumberOfBytesToMap // 
				
						要映射的字节数,为
				
				0
				
						则映射整个文件
						
								
								
						
				
		
		
				
						)
						
								
								
						
				
		
		
				4
				
						.
				
				BOOL  UnmapViewOfFile( LPCVOID  lpBaseAddress ) 
		
		
				
						当不再使用内存映射文件时,可以通过
				
				UmmapViewOfFile
				
						函数撤销映射并使用
				
				CloseHandle
				
						函数关闭内存映射文件的句柄。
						
								
								
						
				
		
		
				5
				
						.
				
				BOOL  FlushViewOfFile(
		
		
				
						       LPCVOID   lpBaseAddress,  // 
				
						开始的地址
						
								
								
						
				
		
		
				
						       SIZE_T     dwNumberOfBytesToFlush // 
				
						数据块的大小
						
								
								
						
				
		
		
				
						  
				
				
						)
						
								
								
						
				
		
		
				
						 
				
				
						如果修改了映射视图中的内存,系统会在试图撤销映射或文件映射对象被删除时自动将数据写到磁盘上,但程序也可以根据需要将视图中的数据立即写到磁盘上。
				
		
		
				
						
								二.使用步骤
						
						
								
										
										
								
						
				
		
		
				
						1.  
				
				
						使用
				
				CreateFileMapping
				
						创建一个内存映射文件内核对象,告诉操作系统内存映射文件需要的物理内存大小,这个步骤决定了内存映射文件的用途――究竟是为磁盘上的文件建立内存映射还是为多个进程共享数据建立共享内存。或者使用
				
				OpenFileMapping
				
						打开映射文件内核对象。
						
								
								
						
				
		
		
				
						2.  
				
				
						映射文件映射对象的全部或一部分到进程的地址空间,可以认为该操作是为文件中的内容分配线型地址空间,并将线型地址和文件内容对应起来,完成该操作的函数是
				
				MapViewOfFile
				
						。
						
								
								
						
				
		
		
				
						 
				
		
		
				
						
								三.使用内存映射文件读文件的具体过程可以这样:
						
						
								
										
										
								
						
				
		
		
				
						(1)        
				
				
						调用
				
				CreateFile
				
						函数打开想要映射的文件,得到文件句柄
				
				hFile
				
						。
						
								
								
						
				
		
		
				
						(2)        
				
				
						调用
				
				CreateFileMapping
				
						函数,并传入文件句柄
				
				hFile
				
						,为该文件创建一个内存映射内核对象,得到内存映射文件的句柄
				
				hMap
				
						。
						
								
								
						
				
		
		
				
						(3)        
				
				
						调用
				
				MapViewOfFile
				
						函数映射整个文件或一部分到进程的虚拟地址空间。该函数返回文件映射到内存后的起始地址。使用指向这个地址的指针就可以读取文件的内容了。
						
								
								
						
				
		
		
				
						(4)        
				
				
						调用
				
				UnmapViewOfFile
				
						函数来解除文件映射。
						
								
								
						
				
		
		
				
						(5)        
				
				
						调用
				
				CloseHandle
				
						函数关闭文件对象,必须传入内存映射文件句柄
				
				hMap
		
		
				
						(6)        
				
				
						调用
				
				CloseHandle
				
						函数关闭文件对象,必须传入文件句柄
				
				hFile
				
						。
						
								
								
						
				
		
		
				
						 
				
		
		
				
						
								四.进程间共享内存:
						
						
								
										
										
								
						
				
		
		
				
						共享内存主要是通过映射机制实现的。
				
				Windows
				
						下进程的地址空间是相互隔离的,但在物理上却是重叠的。所谓的重叠是指同一块内存区域可能被多个进程同时使用。当调用
				
				CreateFileMapping
				
						创建命名的内存映射文件对象时,
				
				Windows
				
						即在物理内存中申请了一块指定大小的内存区域,返回文件映射对象的新句柄
				
				hMap
				
						。为了能够访问这块区域必须调
				
				MapViewOfiFile
				
						函数,促使
				
				Windows
				
						将此内存空间映射到进程的地址空间中。当在其他进程中访问这块区域时,则必须使用
				
				OpenFileMapping
				
						函数来取得对象句柄
				
				hMap
				
						,并调用
				
				MapViewOfFile
				
						函数得到此内存空间的一个映射。这样一来,系统就把同一块内存区域映射到了不同进程的地址空间中,从而达到共享内存的目的。
				
		
		
				一段实例代码:
 BOOL     bRet     = TRUE;
    HANDLE   hMapFile = NULL;
    FILEMAP* pFileMap = NULL;
    g_hFileMap = ::CreateFileMapping(INVALID_HANDLE_VALUE,
        NULL, 
        PAGE_READWRITE, 
        0, 
        sizeof(FILEMAP), 
        g_FileMapFlag);
    if (g_hFileMap && ERROR_ALREADY_EXISTS == ::GetLastError())
    {
        pFileMap = (FILEMAP*)::MapViewOfFile(g_hFileMap, FILE_MAP_READ, 0, 0, 0);
        if (pFileMap)
        {
            ATLASSERT(::IsWindow(pFileMap->hForegroundWnd));
            ::PostMessage(pFileMap->hForegroundWnd, WM_SYSCOMMAND, SC_RESTORE, 0);
            ::SetForegroundWindow(pFileMap->hForegroundWnd);
            bRet = FALSE;
        }
        ::UnmapViewOfFile(pFileMap);
    }
		
	posted on 2009-04-14 00:34 
-274°C 阅读(1567) 
评论(1)  编辑  收藏  所属分类: 
C++