文件映射原理及实现

Posted 那时是什么时候

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了文件映射原理及实现相关的知识,希望对你有一定的参考价值。

  1. 文件内容关联进程虚拟地址空间。

  1. 文件视图是虚拟地址空间的一部分,进程可访问。

  1. 文件映射允许进程使用随机IO和顺序IO。

  1. 进程之间使用文件映射共享数据。

  1. 进程高效处理大数据文件,例如数据库,不需要映射整个文件到内存。

  1. 进程写和读文件视图使用指针,动态分配内存。

  1. 使用文件映射能够提供访问效率,因为文件存在磁盘,而文件视图存在内存。

  1. 进程可以操作文件视图使用VirtualProtect函数。

这张图可以解释了文件映射对象和文件视图的关系。

  1. 硬盘文件想要映射到进程内存,首先要获得文件映射对象,文件映射对象仅包含文件的一部分,由磁盘文件提供支持。

  1. 若系统交换出了文件映射对象页,任何对文件映射对象的改变都会写入到文件。如果系统换回时,会立马改变文件的内容。主要目的是文件映射对象修改后保持与本地文件的数据一致性。

  1. 文件视图仅包含文件映射对象的一部分。进程通过操作文件视图达到操作文件的目的。

  1. 进程可以创建多个文件视图从一个文件映射对象。文件视图存在于进程的虚拟内存空间中。

  1. 当进程需要其他数据时,当前文件视图不能提供,进程会卸载当前文件视图并创建一个新的文件视图。

  1. 多个进程使用同一个文件映像对象创建视图,数据是一致的。文件视图会包含本地文件完全相同的拷贝。

  1. 进程不能共享存储在远程计算机的文件。

创建文件映射对象:

  1. 调用CreateFile 打开文件,打开模式需要选择独占模式,防止其他进程能够写入到被映射的文件部分。

  1. 文件句柄需要一直保持打开,直到进程不再需要文件映射对象。

  1. 简单的方法是获取独占访问并且对CreateFile的参数fdwShareMode 指定为0。

  1. 创建的文件句柄会被CreateFileMapping调用用来创建文件映射对象。返回文件创建对象的句柄。

  1. CreateFileMapping 返回的文件对象句柄会用来创建文件对象视图。

  1. 如果文件映射对象超过了文件大小,需要扩大文件,在CreateFileMapping返回之前。

  1. dwMaximumSizeHighdwMaximumSizeLow 两个CreateFileMapping函数参数允许指定字节的文件被映射。

  1. 不想要改变映射的文件对象,可以dwMaximumSizeHigh和dwMaximumSizeLow设置为0。

  1. 文件映射对象一旦被创建,大小是不能改变的。

创建文件视图:

  1. 文件分配粒度为64K。

  1. 如果想要view 1K,文件视图开始从135K开始。那么64K的倍数离135K最近是128K开始。

  1. 128K+8=136K因此偏移7K,所以文件视图开始为128K+偏移7K。

/*
   This program demonstrates file mapping, especially how to align a
   view with the system file allocation granularity.
*/

#include <windows.h>
#include <stdio.h>
#include <tchar.h>

#define BUFFSIZE 1024 // size of the memory to examine at any one time

#define FILE_MAP_START 138240 // starting point within the file of
                              // the data to examine (135K)

/* The test file. The code below creates the file and populates it,
   so there is no need to supply it in advance. */

TCHAR * lpcTheFile = TEXT("fmtest.txt"); // the file to be manipulated

int main(void)

  HANDLE hMapFile;      // handle for the file's memory-mapped region
  HANDLE hFile;         // the file handle
  BOOL bFlag;           // a result holder
  DWORD dBytesWritten;  // number of bytes written
  DWORD dwFileSize;     // temporary storage for file sizes
  DWORD dwFileMapSize;  // size of the file mapping
  DWORD dwMapViewSize;  // the size of the view
  DWORD dwFileMapStart; // where to start the file map view
  DWORD dwSysGran;      // system allocation granularity
  SYSTEM_INFO SysInfo;  // system information; used to get granularity
  LPVOID lpMapAddress;  // pointer to the base address of the
                        // memory-mapped region
  char * pData;         // pointer to the data
  int i;                // loop counter
  int iData;            // on success contains the first int of data
  int iViewDelta;       // the offset into the view where the data
                        //shows up

  // Create the test file. Open it "Create Always" to overwrite any
  // existing file. The data is re-created below
  hFile = CreateFile(lpcTheFile,
                     GENERIC_READ | GENERIC_WRITE,
                     0,
                     NULL,
                     CREATE_ALWAYS,
                     FILE_ATTRIBUTE_NORMAL,
                     NULL);

  if (hFile == INVALID_HANDLE_VALUE)
  
    _tprintf(TEXT("hFile is NULL\\n"));
    _tprintf(TEXT("Target file is %s\\n"),
             lpcTheFile);
    return 4;
  

  // Get the system allocation granularity.
  GetSystemInfo(&SysInfo);
  dwSysGran = SysInfo.dwAllocationGranularity;

  // Now calculate a few variables. Calculate the file offsets as
  // 64-bit values, and then get the low-order 32 bits for the
  // function calls.

  // To calculate where to start the file mapping, round down the
  // offset of the data into the file to the nearest multiple of the
  // system allocation granularity.
  dwFileMapStart = (FILE_MAP_START / dwSysGran) * dwSysGran;
  _tprintf (TEXT("The file map view starts at %ld bytes into the file.\\n"),
          dwFileMapStart);

  // Calculate the size of the file mapping view.
  dwMapViewSize = (FILE_MAP_START % dwSysGran) + BUFFSIZE;
  _tprintf (TEXT("The file map view is %ld bytes large.\\n"),
            dwMapViewSize);

  // How large will the file mapping object be?
  dwFileMapSize = FILE_MAP_START + BUFFSIZE;
  _tprintf (TEXT("The file mapping object is %ld bytes large.\\n"),
          dwFileMapSize);

  // The data of interest isn't at the beginning of the
  // view, so determine how far into the view to set the pointer.
  iViewDelta = FILE_MAP_START - dwFileMapStart;
  _tprintf (TEXT("The data is %d bytes into the view.\\n"),
            iViewDelta);

  // Now write a file with data suitable for experimentation. This
  // provides unique int (4-byte) offsets in the file for easy visual
  // inspection. Note that this code does not check for storage
  // medium overflow or other errors, which production code should
  // do. Because an int is 4 bytes, the value at the pointer to the
  // data should be one quarter of the desired offset into the file

  for (i=0; i<(int)dwSysGran; i++)
  
    WriteFile (hFile, &i, sizeof (i), &dBytesWritten, NULL);
  

  // Verify that the correct file size was written.
  dwFileSize = GetFileSize(hFile,  NULL);
  _tprintf(TEXT("hFile size: %10d\\n"), dwFileSize);

  // Create a file mapping object for the file
  // Note that it is a good idea to ensure the file size is not zero
  hMapFile = CreateFileMapping( hFile,          // current file handle
                NULL,           // default security
                PAGE_READWRITE, // read/write permission
                0,              // size of mapping object, high
                dwFileMapSize,  // size of mapping object, low
                NULL);          // name of mapping object

  if (hMapFile == NULL)
  
    _tprintf(TEXT("hMapFile is NULL: last error: %d\\n"), GetLastError() );
    return (2);
  

  // Map the view and test the results.

  lpMapAddress = MapViewOfFile(hMapFile,            // handle to
                                                    // mapping object
                               FILE_MAP_ALL_ACCESS, // read/write
                               0,                   // high-order 32
                                                    // bits of file
                                                    // offset
                               dwFileMapStart,      // low-order 32
                                                    // bits of file
                                                    // offset
                               dwMapViewSize);      // number of bytes
                                                    // to map
  if (lpMapAddress == NULL)
  
    _tprintf(TEXT("lpMapAddress is NULL: last error: %d\\n"), GetLastError());
    return 3;
  

  // Calculate the pointer to the data.
  pData = (char *) lpMapAddress + iViewDelta;

  // Extract the data, an int. Cast the pointer pData from a "pointer
  // to char" to a "pointer to int" to get the whole thing
  iData = *(int *)pData;

  _tprintf (TEXT("The value at the pointer is %d,\\nwhich %s one quarter of the desired file offset.\\n"),
            iData,
            iData*4 == FILE_MAP_START ? TEXT("is") : TEXT("is not"));

  // Close the file mapping object and the open file

  bFlag = UnmapViewOfFile(lpMapAddress);
  bFlag = CloseHandle(hMapFile); // close the file mapping object

  if(!bFlag)
  
    _tprintf(TEXT("\\nError %ld occurred closing the mapping object!"),
             GetLastError());
  

  bFlag = CloseHandle(hFile);   // close the file itself

  if(!bFlag)
  
    _tprintf(TEXT("\\nError %ld occurred closing the file!"),
           GetLastError());
  

  return 0;

以上是关于文件映射原理及实现的主要内容,如果未能解决你的问题,请参考以下文章

ZIP压缩算法详细分析及解压实例解释

MyBatis框架中Mapper映射配置的使用及原理解析 配置篇 Configuration

hibernate工作原理及为啥要用

转载host文件的工作原理及应用

MyBatis框架中Mapper映射配置的使用及原理

哈希表原理及简单设计