内存映射文件(Memory-Mapped File)

1. 概念

内存映射文件是一种将文件内容直接映射到进程虚拟地址空间的技术。通过这种方式,文件不再像传统 I/O 那样需要通过 read()/write() 等系统调用进行显式的数据传输,而是可以直接像访问内存一样访问文件内容。

当一个文件被内存映射时,操作系统会:

  1. 在进程的虚拟地址空间中开辟一块区域。

  2. 将这块虚拟地址区域与磁盘上的文件(或文件的一部分)建立关联。

  3. 当进程访问这块虚拟内存区域时,实际访问的就是文件中的数据。

2. 它为了实现什么作用?(主要目的)

内存映射文件主要为了实现以下作用:

3. 存在意义是什么?

内存映射文件的存在意义在于它提供了一种高性能、高效率、且更为自然的文件 I/O 和 IPC 机制,解决了传统 I/O 模式的一些痛点:

4. 和文件系统的联系是什么?

内存映射文件与文件系统有着本质的、不可分割的联系

  1. 文件是基础:内存映射的底层对象始终是文件系统中的一个文件。没有文件系统,就没有文件,也就无法进行内存映射。

  2. 文件系统提供结构化存储:文件系统负责将文件数据逻辑地组织在磁盘上,并提供文件名、目录结构、权限等元数据。内存映射需要这些信息来定位磁盘上的文件数据。

  3. 文件系统管理数据块:当进程访问映射区域的某个虚拟页面时,如果该页面不在物理内存中(缺页),操作系统会通知文件系统,由文件系统负责将对应的文件数据块从磁盘加载到物理内存中。同样,当修改后的页面需要写回磁盘时(脏页回写),也是由文件系统负责将数据写回到文件对应的磁盘块。

  4. 一致性维护:当文件被内存映射并修改时,操作系统(通过文件系统)需要确保内存中的修改最终会被同步回磁盘上的文件,以保持数据的一致性。

  5. 权限管理:内存映射文件的访问权限(读/写/执行)直接继承自底层文件的权限,并通过文件系统的权限检查机制进行管理。

  6. 持久化存储:内存映射文件的修改最终会通过文件系统写回到磁盘,实现数据的持久化存储,这是与纯粹的共享内存(如 shm_openmmap MAP_ANONYMOUS)的关键区别,后者通常不与永久文件关联。

简而言之,内存映射文件是操作系统虚拟内存机制与文件系统I/O机制的深度融合。它将文件系统中的持久化数据,通过虚拟内存技术,“投影”到进程的地址空间中,从而实现高效的访问和管理。

总结图示:

+-------------------------------------------------+
|               用户进程虚拟地址空间             |
|                                                 |
| +---------------------------------------------+ |
| |  ...                                      | |
| |  [虚拟内存区域] <-- 内存映射文件区域        | |
| |  (例如: 从虚拟地址 0x80000000 开始)         | |
| |  (访问这块区域就像访问内存数组一样)         | |
| +---------------------------------------------+ |
|  ...                                          |
+-------------------------------------------------+
          |                               ^
          | (缺页中断/写回请求)         | (数据从磁盘加载)
          V                               |
+-------------------------------------------------+
|               操作系统内核                 |
|                                                 |
| +---------------------------------------------+ |
| |   内存管理单元 (MMU)                       | |
| |   (处理虚拟地址到物理地址转换)           | |
| |                                             | |
| |   页面置换算法 (当物理内存不足时)          | |
| |                                             | |
| |   文件系统 (负责文件查找、分配、读写)      | |
| |   (通过 FCB/i-node 定位文件数据块)         | |
| +---------------------------------------------+ |
          |                               ^
          | (物理 I/O 请求)             | (磁盘数据)
          V                               |
+-------------------------------------------------+
|                 物理内存 (RAM)                 |
|                                                 |
| +---------------------------------------------+ |
| |  文件数据页面 (通过映射加载到这里)        | |
| +---------------------------------------------+ |
          |                               ^
          | (物理块访问)                  | (数据从磁盘)
          V                               |
+-------------------------------------------------+
|              磁盘 (文件系统存储)               |
|                                                 |
| +---------------------------------------------+ |
| |  文件数据块 (存储在文件系统的特定位置)      | |
| |  (由 FCB/i-node 维护其物理地址)             | |
| +---------------------------------------------+ |
+-------------------------------------------------+

如上图,文件经过内存映射后,对文件对应地址的访问就不再需要通过 read()/write()
系统调用,而是可以直接访问对应的虚拟内存,通过 MMU 映射和缺页异常处理来访问到对
应磁盘中的文件信息。