根据我对 mmap() 的研究,我了解到 mmap 仅当通过页面错误触及虚拟内存地址时才使用请求分页将数据复制到内核页面缓存。
如果我们正在读取大于页面缓存的文件,则页面缓存中的一些陈旧页面将必须被换出回收。所以我的问题是,页表是否会更新以将相应的虚拟内存地址映射到缓存中旧的过时页面的地址(现在包含新数据)?这是怎么发生的?这是 mmap() 系统调用的一部分吗?
根据我对 mmap() 的研究,我了解到 mmap 仅当通过页面错误触及虚拟内存地址时才使用请求分页将数据复制到内核页面缓存。
如果我们正在读取大于页面缓存的文件,则页面缓存中的一些陈旧页面将必须被换出回收。所以我的问题是,页表是否会更新以将相应的虚拟内存地址映射到缓存中旧的过时页面的地址(现在包含新数据)?这是怎么发生的?这是 mmap() 系统调用的一部分吗?
调用时
mmap()
,它会在进程的虚拟地址空间中创建到指定文件的映射。此映射仅设置这些页面在实际访问时加载的能力,它尚未将任何内容加载到内存中。当您访问这些页面时,会生成页面错误,页表条目会更新以将虚拟地址映射到新加载页面的物理地址,然后您就可以访问该文件。这发生在filemap_fault
.如果您访问已被逐出的映射页面,这也是它的工作原理:内核处理页面错误,将文件内容放回到页面中,从应用程序的角度来看,什么也没有发生。
这里本身没有什么特别的
mmap()
——这就是 Linux 内核中需求分页的一般工作方式,几乎用于所有东西——甚至是常规程序内存和文件缓存条目。请注意,当使用 读取时
mmap()
,内核通常会使用预读来加载更多内容,而不仅仅是生成页面错误的单个页面,除非有迹象表明这没有帮助,例如MADV_RANDOM
或MADV_DONTNEED
(由用户),或MMAP_LOTSAMISS
(内核启发式)。