mmap'ed内存何时以及如何换入和换出?

When and how is mmap'ed memory swapped in and out?

以我的理解,mmap'ing 一个适合 RAM 的文件就像将文件放在内存中一样。

假设我们有16G的内存,我们先mmap一个10G的文件,暂时用一下。这在访问方面应该是相当有效的。如果我们然后映射第二个 10G 文件,是否会导致第一个文件被换出?还是其中的一部分?如果是这样,这将在什么时候发生?在 mmap 调用时,还是在访问新加载文件的内存区域时?

如果我们想再次访问第一个文件指针的内存,是否会再次加载交换文件?那么,假设我们在对应于第一个文件和第二个文件的内存之间交替读取,这会导致灾难性的性能吗?

最后,如果其中任何一个是正确的,mmap 几个较小的文件会更好吗?

你的问题没有明确的答案,因为交换 in/out 是由你的内核处理的,每个内核都有不同的实现(并且 linux 本身根据你的使用情况提供不同的配置文件, RT, 桌面, 服务器...)

不过,一般来说,无论您在内存中加载什么,都是使用页面完成的,因此内存中的 mmap 文件是通过所有级别的内存(缓存、RAM 和交换)之间的页面加载(和卸载)的. 然后,如果您将两个 10GB 数据加载到内存中,您将在 RAM 和 Swap 之间拥有部分数据,内核将尝试将您现在可能使用的页面保留在 RAM 中,并猜测您接下来将加载什么.

这意味着如果您真正随机访问两个文件中的几个字节数据,您应该期望糟糕的性能,如果您从或者,您 应该 期待良好的性能。

您可以在虚拟内存理论中阅读有关内核分页的更多详细信息:

如前所述,您的文件将按页面访问;在 x86_64(和 IA32)架构上,一个页面通常为 4096 字节。因此,在 mmap 时间加载的文件很少(如果有的话)。第一次访问任一文件中的某个页面时,内核将生成一个 page fault 并加载你的一些文件。内核可能会预取页面,因此可能会加载多个页面。是否这样做取决于您的访问模式。

一般来说,如果您的 working set 适合内存,您的表现应该不错。也就是说,如果您只是定期访问两个文件中的 3G 文件,那么只要您的进程有 3G 的 RAM 可用,通常情况应该没问题。

在 64 位系统上,没有理由拆分文件,如果您需要的部分适合 RAM 就没问题。

请注意,如果您映射现有文件,则不需要交换 space 来读取该文件。当一个对象由文件系统上的文件支持时,内核可以从该文件读取而不是交换 space。但是,如果您在对 mmap 的调用中指定 MMAP_PRIVATE,则可能需要交换 space 来保留更改的页面,直到您调用 msync。