当我们将文件映射到内存时,需要进行系统调用。对文件的后续访问是否需要系统调用,还是映射到内存中实际页面缓存的进程的虚拟内存页?
更新: 我还想知道的是,如果多个进程通过mmap访问同一个文件。他们将访问相同的物理内存部分写。
答案 0 :(得分:4)
当您映射文件时,Linux会在MMU(内存管理单元)中创建条目。 MMU监视CPU对真实RAM的所有读写操作。这样,它就知道您何时访问mmap()
返回的内存部分。读取尚未存在于实际RAM中的部分将导致页面错误。 MMU将捕获它们并调用内核例程将文件的正确部分加载到某个RAM的RAM中,然后它将更新MMU表中的条目,这样看起来数据现在位于mmap()
的地址给你。事实上,它将在其他地方,但MMU将使这完全透明。
当您写入内存时,MMU会将修改后的页面标记为“脏”。当它们被刷新时(因为您访问了更多文件或因为您调用了munmap()
),所以更改将被写入磁盘。
因此,每次发生页面错误和脏页面刷新时,都会发生系统调用。但由于页面为4或8KB,因此很少发生。此外,内核将一次加载多个页面,因此系统调用次数再次减少。最后,相同的代码用于实现交换,因此它非常优化。
所有这些效果使mmap如此高效。
答案 1 :(得分:3)
无需额外的系统调用 (按您的流程) ,您只需像常规内存一样访问它。完成该文件后,只需致电munmap
。
返回值
成功时,
mmap()
返回指向映射区域的指针。 出错时,值为MAP_FAILED
(即 是,(void *) - 1)返回,和 errno设置得恰当。上 成功,munmap()
返回0,开启 失败-1,并设置errno
(可能 到EINVAL
)。
See the man page here for details
编辑澄清:
我说该函数将文件映射到调用进程的内存空间,并返回指向内存块开头的指针。
例如,如果您有两个不同的进程使用MAP_SHARED
标志映射相同的文件,则每个进程将访问相同的物理内存,但该内存可能映射到每个进程的虚拟内存中的不同位置空间,即mmap在每个进程的虚拟内存空间中返回的指针可能不相等。
这提出了这样的观点:如果你需要在共享内存块中存储指针,那么这些指针只有在相对于块/文件的开头存储为偏移量时才有用,并且它们只能够有用地指向块/文件内部的位置。