当2个程序映射同一个文件时,mmap如何工作

时间:2016-01-30 18:26:33

标签: c linux mmap virtual-memory page-tables

我在查看man mmap时试图了解mmap的工作原理。

据我了解,它添加了一个映射到页面表,该映射表在文件和虚拟地址之间进行映射(这是给定的地址void *addr

那么,当2个程序映射同一个文件时会发生什么? 页表中是否有2个条目,每个程序一个?

2 个答案:

答案 0 :(得分:3)

  

那么,当2个程序映射同一个文件时会发生什么?页表中是否有2个条目,每个程序一个?

在现代操作系统中,每个进程都有自己的内存页表,可以指向与其他用户和内核进程共享的物理内存页。

  

使用MAP_SHARED,共享此映射:对映射此文件的其他进程可以看到对映射的更新,并将其传递到基础文件。在调用msync(2)或munmap()之前,实际上可能不会更新该文件。

这看起来非常有趣,但有很多警告:

  • 同一文件的两个进程映射的实际页面可能位于每个进程中的相同地址或不同地址,将指针存储到此共享内存中可能不允许另一个使用它们的过程,因为它们可能指向不一致的地址。

  • 实现可能会对两个映射使用相同的物理内存页面:出于微妙的原因(缓存策略,不同步读取......),即使它是相同的物理内存,也可以通过一个进程到其内存可能不会立即反映在其他进程的内存中。

因此,修改可能会或可能不会显示其他进程正在映射文件,也不会通过readFILE*流API读取它。

如果其中一个进程调用msync(),则修改应该在所有映射中都可见,并且对于文件的所有尚未读取的部分,请记住FILE*流API可能已经缓存了一些数据在内部非共享缓冲区中:不会反映此区域中的修改。

结论:使用这些机制实现进程间通信是有风险且不可靠的。行为可能取决于系统特定的特性,例如OS策略,CPU和缓存架构,使用的RAM类型,时钟速度以及谁知道还有什么。依靠可能确实使用mmapped内存实现的经过验证的API更安全,但前提是它知道提供正确的语义。

答案 1 :(得分:1)

实际的系统实现是不同的。存在过度简化的风险(并省略分页):

mmap会将物理页面框架映射到文件。

  

那么,当2个程序映射同一个文件时会发生什么?页表中是否有2个条目,每个程序一个?

如果两个进程(P和Q)映射到同一个文件,则P和Q将各自拥有自己的页表;每个页表都有条目映射到同一个物理页面帧(可以映射到P和Q中的不同地址)。