我试图mmap
在查看man mmap时了解其工作原理。
据我了解,它向页表添加了一个映射,该映射在文件和虚拟地址之间进行映射(这是给定的地址void *addr
)
那么,当两个程序映射同一个文件时会发生什么?页表中是否有 2 个条目,每个程序一个?
我试图mmap
在查看man mmap时了解其工作原理。
据我了解,它向页表添加了一个映射,该映射在文件和虚拟地址之间进行映射(这是给定的地址void *addr
)
那么,当两个程序映射同一个文件时会发生什么?页表中是否有 2 个条目,每个程序一个?
那么,当两个程序映射同一个文件时会发生什么?页表中是否有 2 个条目,每个程序一个?
在现代操作系统中,每个进程都有自己的内存页表,它可能指向与其他用户和内核进程共享的物理内存页。
使用
MAP_SHARED
,此映射是共享的:映射的更新对映射此文件的其他进程可见,并传递到底层文件。在调用 msync(2) 或 munmap() 之前,该文件实际上可能不会被更新。
这看起来很有趣,但有很多警告:
两个进程为同一文件映射的实际页面可能位于每个进程的相同地址或不同地址,将指针存储到此共享内存中可能不允许其他进程使用它们,因为它们可能指向不一致的地址。
实现可能对两个映射使用相同的物理内存页面:出于微妙的原因(缓存策略,不同步读取......),即使它是相同的物理内存,一个进程对其内存所做的修改也可能不会立即反映在其他进程的内存中。
read
因此,修改可能对映射文件或通过FILE*
流 API读取文件的其他进程可见,也可能不可见。
如果其中一个进程调用msync()
,则修改应该在所有映射中以及文件的所有尚未读取的部分中可见,请记住FILE*
流式 API 可能已在内部非共享缓冲区中缓冲了一些数据:此区域中的修改将不会被反映.
结论:使用这些机制来实现进程间通信是有风险和不可靠的。行为可能取决于系统特定的特性,例如操作系统策略、CPU 和缓存架构、正在使用的 RAM 类型、时钟速度以及谁知道还有什么。依靠经过验证的 API 更安全,这些 API 确实可以使用 mmapped 内存实现,但前提是它知道提供正确的语义。
实际的系统实现是不同的。有过度简化的风险(并在此处省略分页):
mmap 将物理页框映射到文件。
那么,当两个程序映射同一个文件时会发生什么?页表中是否有 2 个条目,每个程序一个?
如果两个进程(P 和 Q)映射到同一个文件,那么 P 和 Q 将各自拥有自己的页表;每个页表都将具有到相同物理页框的条目映射(可以映射到 P 和 Q 内的不同地址)。