Linux mmap:映射文件会立即加载到内存中吗?

Linux mmap:映射文件会立即加载到内存中吗?,linux,mmap,Linux,Mmap,从手册中,我只知道mmap()将文件映射到虚拟地址空间,因此可以随机访问该文件。但是,我不清楚映射文件是否立即加载到内存中?我猜内核是按页管理映射内存的,它们是按需加载的,如果我只做一些读写操作,那么只会加载一些页。正确吗?是的。mmap的全部要点是,is管理内存的效率高于将所有内容都存储到内存中 当然,在某些情况下,任何给定的实现都可能决定一次性读取整个文件更有效,但这对于调用mmap的程序来说应该是透明的。是的,mmap创建了一个映射。它通常不会读取映射到内存中的所有内容。如果您希望这样做,

从手册中,我只知道mmap()将文件映射到虚拟地址空间,因此可以随机访问该文件。但是,我不清楚映射文件是否立即加载到内存中?我猜内核是按页管理映射内存的,它们是按需加载的,如果我只做一些读写操作,那么只会加载一些页。正确吗?

是的。
mmap
的全部要点是,is管理内存的效率高于将所有内容都存储到内存中


当然,在某些情况下,任何给定的实现都可能决定一次性读取整个文件更有效,但这对于调用
mmap
的程序来说应该是透明的。是的,mmap创建了一个映射。它通常不会读取映射到内存中的所有内容。如果您希望这样做,您可以使用mlock/mlockall系统调用强制内核将映射的内容读入RAM中(如果适用)。

否,是,可能。视情况而定

调用
mmap
通常只意味着对于您的应用程序,映射文件的内容映射到其地址空间,就好像文件加载在那里一样。或者,就好像文件真的存在于内存中,就好像它们是同一个文件一样(其中包括写回磁盘的更改,假设您具有写访问权限)

不多也不少。它没有加载东西的概念,应用程序也不知道这意味着什么

应用程序并不真正了解内存之类的东西,尽管虚拟内存系统让它看起来像这样。应用程序可以“查看”(和访问)的内存可能与实际物理内存相对应,也可能与实际物理内存相对应,原则上可以随时更改,而无需事先警告,也没有明显的原因(对应用程序来说很明显)。
除了可能由于页面错误而经历一个小的延迟之外,应用程序(原则上)完全不知道任何这样的事情发生,并且对它几乎没有控制权1

由于遇到故障,应用程序通常会根据需要从映射文件(包括主可执行文件!)加载页面。然而,操作系统通常会尝试推测性地预取数据以优化性能

实际上,调用
mmap
将立即开始(异步)从映射开始预取页面,直到达到特定实现指定的大小。这意味着,原则上,对于小文件,答案是“是”,对于大文件,答案是“否”。
但是,
mmap
不会阻止等待readahead的完成,这意味着您不能保证在
mmap
返回后立即将任何文件放入RAM中(无论如何,您在任何时候都不能保证!)。到目前为止,答案是“可能”

在Linux下,我上次查看时,默认的预取大小是31个块(~127k)——但这可能已经改变了,加上它是一个可调参数。当触摸预取区域附近或末端的页面时,会异步预取更多页面。
如果您向
madviurandom
提示了
madvise
,则预取“不太可能发生”,在Linux下,这将完全禁用预取

另一方面,给出
MADV_SEQUENTIAL
提示将从映射开始异步地“更积极地”预取(并且可能更快地丢弃访问的页面)。在Linux下,“更具攻击性”意味着是正常数量的两倍

给出
MADV_WILLNEED
提示意味着(但不保证)尽快加载给定范围内的所有页面(因为您说您将访问它们)。操作系统可能会忽略这一点,但在Linux下,它被视为一个命令而不是一个提示,高达进程的最大RSS限制和实现指定的限制(如果我没记错的话,是物理RAM量的1/2)。
请注意,
MADV_DONTNEED
在Linux下的实现可能是错误的。提示不是按照POSIX指定的方式解释的,也就是说,您暂时可以将页面调出,但您的意思是放弃页面。这对只读映射页面没有太大的区别(除了一个小的延迟,你说可以),但它确实对其他一切都有影响。
特别是,使用
MADV_DONTNEED
认为Linux会在操作系统懒散地将不需要的页面写入磁盘后释放这些页面,这不是事情的工作方式!您必须明确同步,或为惊喜做好准备

在调用
mmap
之前,在文件描述符上调用了
readahead
(或者,之前已经读/写了文件),实际上文件的内容将立即进入RAM。
然而,这仅仅是一个实现细节(统一虚拟内存系统),并且受制于系统上的内存压力

调用
mlock
将立即将请求的页面加载到RAM中,假设调用成功。它会一直阻塞,直到所有页面都实际存在,并且您可以保证这些页面将保留在RAM中,直到您解锁它们


1存在查询(
mincore
)特定范围内的任何或所有页面是否在此时实际存在的功能,以及在没有任何硬保证的情况下提示操作系统您希望看到发生什么的功能(
madvise
),最后一个功能是强制在内存中存在有限的页面子集(
mlock
),用于私有进程

2由于缺少特权和超过配额或存在的物理RAM量,它可能不会。默认情况下,mmap()仅配置映射和返回(fast)

Linux(至少)有一个选项MAP_POPULATE(请参阅“man mmap”),用于