内存映射文件

31 篇文章 1 订阅
 

本文内容全部引子windows核心编程。只因今天详细的看了一下,特做了摘抄而已!

内存映射文件最好用于只读独占的方式打开,因为如果采用可写的方式的话,不能保证一个进程的修改立

即在另一个进程生效。以独占方式打开就禁止了其他进程的访问。下面详细介绍一下使用文件映射的步骤

和方法:

步骤1:创建或打开文件内核对象
HANDLE CreateFile(
   PCSTR pszFileName,
   DWORD dwDesiredAccess,  //GENERIC_READ 只读
   DWORD dwShareMode,    //0 独占
   PSECURITY_ATTRIBUTES psa,
   DWORD dwCreationDisposition,
   DWORD dwFlagsAndAttributes,
   HANDLE hTemplateFile);

步骤2:创建一个文件映射内核对象
调用C r e a t e F i l e函数,就可以将文件映像的物理存储器的位置告诉操作系统。你传递的路径名

用于指明支持文件映像的物理存储器在磁盘(或网络或光盘)上的确切位置。这时,必须告诉系统,文件

映射对象需要多少物理存储器。若要进行这项操作,可以调用C r e a t e F i l e M a p p i n g函数


HANDLE CreateFileMapping(
   HANDLE hFile,
   PSECURITY_ATTRIBUTES psa,
   DWORD fdwProtect,  //PAGE_READONLY
   DWORD dwMaximumSizeHigh,
   DWORD dwMaximumSizeLow,
   PCTSTR pszName);
这里需要说明一点的是fdwProtect中的PAGE_WRITECOPY当文件映射对象被映射时,可以读取和写入文件的

数据。如果写入数据,会导致页面的私有拷贝得以创建。必须已经将G E N E R I C _ R E A D或G E N E

R I C _ W R I T E传递给C r e a t e F i l e

步骤3:将文件数据映射到进程的地址空间
当创建了一个文件映射对象后,仍然必须让系统为文件的数据保留一个地址空间区域,并将文件的数据作

为映射到该区域的物理存储器进行提交。可以通过调用M a p Vi e w O f F i l e函数来进行这项操作:

PVOID MapViewOfFile(
   HANDLE hFileMappingObject,
   DWORD dwDesiredAccess, //FILE_MAP_READ
   DWORD dwFileOffsetHigh,
   DWORD dwFileOffsetLow,
   SIZE_T dwNumberOfBytesToMap);
如果在调用M a p Vi e w O f F i l e函数时设定了F I L E _ M A P _ C O P Y标志,系统就会从系统

的页文件中提交物理存储器。提交的地址空间数量由d w N u m b e r O f B y t e s To M a p参数决定

。只要你不进行其他操作,只是从文件的映像视图中读取数据,那么系统将决不会使用页文件中的这些提

交的页面。但是,如果进程中的任何线程将数据写入文件的映像视图中的任何内存地址,那么系统将从页

文件中抓取已提交页面中的一个页面,将原始数据页面拷贝到该页交换文件中,然后将该拷贝的页面映射

到你的进程的地址空间。从这时起,你的进程中的线程就要访问数据的本地拷贝,不能读取或修改原始数

据。当系统制作原始页面的拷贝时,系统将把页面的保护属性从PA G E _ W R I T E C O P Y改为PA G E

_ R E A D W R I T E。

这时就可以通过返回的视图文件指针对文件进行操作了。

步骤4:从进程的地址空间中撤消文件数据的映像
BOOL UnmapViewOfFile(PVOID pvBaseAddress) //该值必须与调用M a p Vi e w O f F i l e函数返回的

值相同

步骤5和步骤6:关闭文件映射对象和文件对象
CloseHandle(hFileMapping);
CloseHandle(hFile);

详细使用方法举例,这个例子实在是太经典了。学习学习

__int64 Count0s(void)
{
   //Views must always start on a multiple
   //of the allocation granularity
   SYSTEM_INFO sinf;
   GetSystemInfo(&sinf);

   //Open the data file.
   HANDLE hFile = CreateFile("C://HugeFile.Big", GENERIC_READ,
      FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);

   //Create the file-mapping object.
   HANDLE hFileMapping = CreateFileMapping(hFile, NULL, 
      PAGE_READONLY, 0, 0, NULL);

   DWORD dwFileSizeHigh;
   __int64 qwFileSize = GetFileSize(hFile, &dwFileSizeHigh);
   qwFileSize += (((__int64) dwFileSizeHigh) << 32);

   //We no longer need access to the file object's handle.
   CloseHandle(hFile);

   __int64 qwFileOffset = 0, qwNumOf0s = 0;

   while (qwFileSize > 0) 
   {
      // Determine the number of bytes to be mapped in this view
      DWORD dwBytesInBlock = sinf.dwAllocationGranularity;

      if(qwFileSize < sinf.dwAllocationGranularity)
         dwBytesInBlock =(DWORD) qwFileSize;

      PBYTE pbFile = (PBYTE) MapViewOfFile(hFileMapping, FILE_MAP_READ,
         (DWORD)(qwFileOffset >> 32),          // Starting byte
         (DWORD)(qwFileOffset & 0xFFFFFFFF),   // in file
         dwBytesInBlock);                      // # of bytes to map

      // Count the number of Js in this block.
      for(DWORD dwByte = 0; dwByte < dwBytesInBlock; dwByte++)
      {
         if(pbFile[dwByte] == 0)
         qwNumOf0s++;
      }

      // Unmap the view; we don't want multiple views
      // in our address space.
      UnmapViewOfFile(pbFile);

      // Skip to the next set of bytes in the file.
      qwFileOffset += dwBytesInBlock;
      qwFileSize -= dwBytesInBlock;
   }

   CloseHandle(hFileMapping);
   return(qwNumOf0s);
}
这个算法用于映射64 KB(分配粒度的大小)或更小的视图。另外,要记住, M a p Vi e wO f F i l e

函数要求文件的位移是分配粒度大小的倍数。当每个视图被映射到地址空间时,对0的扫描不断进行。当

每个64 KB的文件块已经映射和扫描完毕时,就要通过关闭文件映射对象来对每个文件块进行整理。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值