从手册中,我只知道mmap()将文件映射到虚拟地址空间,因此可以随机访问该文件。但是,我不清楚映射的文件是否立即加载到内存中?我猜想内核会按页面管理映射的内存,并且按需加载它们,如果我仅执行一些读取和写入操作,则只会加载几个页面。这是对的吗?
不,是的,也许。这取决于。
mmap
通常,调用仅意味着将映射文件的内容映射到其应用程序的地址空间,就像文件已加载到应用程序一样。或者,就像文件确实存在于内存中一样,就好像它们是一个文件一样(包括将更改写回到磁盘上,假设您具有写访问权)。
不多不少。它没有加载任何东西的概念,应用程序也不知道这意味着什么。
尽管虚拟内存系统使应用程序看起来像这样,但是应用程序实际上并不了解诸如内存之类的任何东西。应用程序可以“查看”(和访问)的内存可能与实际的物理内存相对应,也可能不与实际的物理内存相对应,并且原则上可以随时更改,而无需事先警告,也没有明显的理由(对您的应用程序来说很明显)。
除了可能由于页面错误而导致一小段延迟之外,应用程序(原则上)完全不知道任何此类事件的发生,并且对此几乎没有控制权1。
通常,由于遇到故障,应用程序将根据需要从映射文件(包括主可执行文件!)中加载页面。但是,操作系统通常会尝试推测性地预取数据以优化性能。
实际上,调用mmap
将立即开始从映射的开始(异步地)预取页面,直到特定的实现指定大小。原则上,这意味着对于小文件,答案为“是”,而对于大文件,答案为“否”。
但是,mmap
不会阻止等待预读完成,这意味着您不能保证mmap
返回后立即将任何文件放入RAM (无论如何,您始终不能保证!)。就此而言,答案是“也许”。
在Linux下,我上次查看时,默认的预取大小为31个块(约127k)-但这可能已更改,而且它是一个可调参数。当触摸预取区域附近或末尾的页面时,更多的页面将被异步预取。
如果你已经暗示MADV_RANDOM
到madvise
,预取是“不太可能发生”,在Linux下这完全禁用预取。
另一方面,给出MADV_SEQUENTIAL
提示将从映射的开始开始异步“更积极地”预取(并且可能会更快地丢弃访问的页面)。在Linux下,“更积极”表示两倍于正常数量。
提供MADV_WILLNEED
提示表明(但不保证)尽快加载给定范围内的所有页面(因为您要说的是访问它们)。操作系统可能会忽略这一点,但是在Linux下,它被视为命令而不是提示,最高为进程的最大RSS限制和实现指定的限制(如果我没记错的话,是物理RAM数量的1/2 )。
请注意,MADV_DONTNEED
可以说在Linux下错误实现了该错误。提示不是用POSIX指定的方式解释的,即您可以暂时将页面分页出来,但是您的意思是丢弃它们。对于只读映射的页面,这没有什么大的区别(除了很小的延迟(您说可以),但这确实很重要)对于其他一切。
特别是,在MADV_DONTNEED
Linux将操作系统懒惰地将它们写入磁盘后,使用Linux来释放不需要的页面的想法是行不通的!您必须明确同步,否则请准备一个惊喜。
已经呼吁readahead
呼吁之前文件描述符mmap
(或者,有过读/写以前的文件),该文件的内容将在实践中确实是在RAM中立即。
但是,这仅是实现细节(统一的虚拟内存系统),并且受系统内存压力的影响。
调用will-mlock
假设成功2-立即将请求的页面加载到RAM中。它会阻塞,直到所有页面都实际存在为止,并且您可以保证这些页面将保留在RAM中,直到您对其进行解锁为止。
mincore
)当前是否确实存在特定范围内的任何页面或所有页面,并且可以在没有任何保证的情况下向OS暗示您 希望 看到的事件的功能( madvise
),最后强制将页面的有限子集显示在 mlock
特权进程的内存( )中的功能。
2可能不是因为缺乏特权,没有超出配额或存在的物理RAM数量。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句