C++ 应用程序中的文件内存映射技术

文件内存映射是一种机制,它允许我们在磁盘上创建一个文件的映射对象。在此之后,不同的进程可以在它们各自的虚拟地址空间中创建这个文件映射对象的视图。一个进程可以在其虚拟地址空间中创建该文件映射对象的一个或多个视图,并对其进行操作。下面展示了文件映射对象的工作原理图:

!image

请务必记住以下几个关键点:

  • 文件位于运行进程的计算机磁盘上。
  • 文件映射对象位于物理内存中。
  • 多个进程可以为同一个文件映射对象创建视图。
  • 文件映射对象可以包含整个文件或文件的一部分。同样,进程的文件视图也可以包含整个文件映射对象或其一部分。
  • 所有副本都是保持一致的,并且与磁盘上存在的数据完全相同

优势

  • 当处理大型文件(如数据库文件)时,这非常有帮助,因为不需要将整个文件都加载到物理内存中。
  • 多个进程可以使用磁盘上的同一个文件进行读写操作。每个进程都可以创建一个新视图,并取消映射当前的文件视图。

创建文件映射对象和文件视图的步骤

步骤 1: 创建或打开一个代表磁盘上文件的文件对象。在这里,我们创建了一个新的文件对象,其句柄为 hFile,命名为 "datafile.txt"

HANDLE CreateFileA(
  LPCSTR                lpFileName,
  DWORD                 dwDesiredAccess,
  DWORD                 dwShareMode,
  LPSECURITY_ATTRIBUTES lpSecurityAttributes,
  DWORD                 dwCreationDisposition,
  DWORD                 dwFlagsAndAttributes,
  HANDLE                hTemplateFile
);

// 使用方式如下 

HANDLE hFile = CreateFile(TEXT("datafile.txt"),
GENERIC_READ | GENERIC_WRITE,
0,          
// 以独占访问方式打开
NULL,
// 无安全属性

// 创建一个新的临时文件
CREATE_NEW,

// 在取消映射视图后删除文件 
FILE_FLAG_DELETE_ON_CLOSE,   
      
        
NULL);
HANDLE CreateFileA(
  LPCSTR                lpFileName,
  DWORD                 dwDesiredAccess,
  DWORD                 dwShareMode,
  LPSECURITY_ATTRIBUTES lpSecurityAttributes,
  DWORD                 dwCreationDisposition,
  DWORD                 dwFlagsAndAttributes,
  HANDLE                hTemplateFile
);

// 使用方式如下 

HANDLE hFile = CreateFile(TEXT("datafile.txt"),
        GENERIC_READ | GENERIC_WRITE,
        0,          // 以独占访问方式打开
        NULL,       // 无安全属性
        CREATE_NEW, // 创建一个新的临时文件
        FILE_FLAG_DELETE_ON_CLOSE,         //在取消映射视图后删除文件
        NULL);

步骤 2: 为该文件创建一个映射对象,其中包含有关如何访问文件及其大小的信息。因此,在创建上述文件后,我们使用其句柄并在物理内存中创建它的映射。

HANDLE CreateFileMappingA(
  HANDLE                hFile,
  LPSECURITY_ATTRIBUTES lpFileMappingAttributes,
  DWORD                 flProtect,
  DWORD                 dwMaximumSizeHigh,
  DWORD                 dwMaximumSizeLow,
  LPCSTR                lpName
);

// 使用方式如下 

HANDLE hFileMapping = ::CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, bufferSize, filename);

步骤 3: 将文件映射对象的全部或一部分从物理内存映射到我们进程的虚拟地址空间。在这里,我们正在创建映射文件的视图,该视图将被进程使用。

LPVOID MapViewOfFile(
  HANDLE hFileMappingObject,
  DWORD  dwDesiredAccess,
  DWORD  dwFileOffsetHigh,
  DWORD  dwFileOffsetLow,
  SIZE_T dwNumberOfBytesToMap
);

// 使用方式如下
void* p = ::MapViewOfFile(hFileMapping, FILE_MAP_ALL_ACCESS, 0, param1, param2);

步骤 4: 清理工作
4(A) 从进程地址空间中取消映射文件映射对象。回溯上述步骤,首先,从进程的地址空间中移除文件视图。

BOOL UnmapViewOfFile(LPCVOID lpBaseAddress
);
// 使用方式如下
UnmapViewOfFile(p);

4(B) 关闭文件映射对象。此步骤将从物理内存中移除文件映射。

CloseHandle(hFileMapping);

4(C) 关闭文件对象。在这里,关闭在磁盘上打开的文件并释放句柄。由于在第一步中我们设置了标志 FILEFLAGDELETEONCLOSE,文件将在这一步之后被删除。

CloseHandle(hFile);

> 注意:

>

>

>

> 1. 请按相同的顺序关闭句柄,否则会导致差异或错误。

> 2. 在尝试删除文件之前,请关闭所有打开的文件句柄。

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。如需转载,请注明文章出处豆丁博客和来源网址。https://shluqu.cn/49449.html
点赞
0.00 平均评分 (0% 分数) - 0