理解内存映射文件

8

我开始阅读有关内存映射IO的内容,但是我对其中的概念有些困难。

到目前为止,这就是我所理解的:

每个进程都有一个虚拟地址空间。内存映射文件在虚拟地址空间中分配了一段特定的地址范围,该范围映射到物理内存上的相同地址。这样,所有由磁盘控制器通过DMA写入内存的内容都将反映到进程中,而无需进行额外的复制。(在非内存映射文件的情况下,CPU将不得不将内容复制到进程的缓冲区中)。

我的疑问:

  • 我的理解正确吗?

  • 如果有多个进程尝试映射文件并且没有连续的内存块可用于直接映射会发生什么情况?


1
我正在删除Java和NIO标签;这似乎与Java无关。 - chrylis -cautiouslyoptimistic-
1个回答

8
内存子系统本身并不了解“文件”,这是一个操作系统的概念,有一些操作系统根本不使用文件。你对mmap的工作原理的理解接近但还有一点偏差。
每个进程都有自己的虚拟地址空间,它可能与物理内存几乎没有关系(许多虚拟地址空间根本没有任何相关的内存,而被交换出去的虚拟内存也没有任何物理内存)。系统使用某种查找表(在x86上称为描述符表),指定什么虚拟地址范围映射到什么物理地址范围。未“常驻”(交换出去,mmap但未加载)的虚拟内存具有“不存在”的条目。
每当程序尝试访问此内存时,CPU会导致页面错误,告诉操作系统在某处找到相应的内容并将其加载到物理内存中。在交换的情况下,内容从交换文件或分区加载;在mmap的情况下,它们从文件系统中的某个位置加载。
将它们加载到物理内存中并更新描述符表的机制可能会有所不同。您描述的是DMA,它允许驱动器控制器直接将内容复制到一块物理内存中,并且零拷贝I/O是一种技术,其中操作系统只创建一个新的描述符映射,告诉处理器将物理内存区域“传送”到程序的地址空间中。这两者在技术上都不是mmap所必需的(操作系统可以手动加载文件并将其复制到程序的新缓冲区中,在读-复制-更新情况下可能会发生这种情况),但现代系统会像您描述的那样执行。
物理内存不一定要连续。当调用POSIX版本的mmap时,操作系统为映射分配length字节,但由于虚拟内存,这些字节可能被分成多个块,并由处理器一起映射。
如果多个进程尝试mmap相同的文件,则操作系统行为取决于访问是只读还是读/写;只读副本可以在许多进程之间共享(例如实际的可执行代码;这就是为什么即使Chrome可能有数十个进程运行,Chrome二进制文件也只存在于内存中一次的原因)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接