问题描述
anonymous memory - 即程序堆和堆栈 - 是 Linux 页面缓存的一部分吗?内核的链接文档没有说明这一点。
但是关于 Page Cache 的维基百科条目包含一个图形(看右上角),它给我的印象是 malloc() 在页面缓存中分配动态内存:
有意义吗?关于 mmap()
,当它用于访问文件时,使用页面缓存是有意义的。也通常用于匿名内存,例如malloc()
和匿名映射通过 mmap()
?
我希望得到一些解释。
谢谢。
编辑 2021-03-14
我决定最好在他们的 mailing-list 上询问内存子系统的内核维护人员。幸运的是 Matthew Wilcox 回应并帮助了我。提取:
- 匿名内存不由
page cache
处理。 - 匿名页面的处理方式有多种——它们可以在
LRU lists
(最近最少使用)上找到,也可以通过page tables
找到。有点临时。 - 维基百科图是错误的。它包含更多的缺陷。
- 如果系统提供交换并且交换匿名内存 - 它进入
swap cache
,而不是page cache
。
解决方法
TLDR:不,除了具有特殊文件系统支持的匿名内存(如 IPC shmem)。
更新:更正了答案以将来自 kernel mailing list discussion 的新信息与 OP 合并。
页面缓存最初是用于快速查找磁盘支持文件的操作系统级内存区域,其原始形式是缓冲区缓存(用于缓存磁盘中的块)。页面缓存的概念是在 1995 年 Linux 诞生后的晚些时候出现的,但前提是相似的,只是一个新的抽象——页面 [1]。 事实上,最终两个缓存合而为一:页面缓存包括缓冲区缓存,或者更确切地说,缓冲区缓存就是页面缓存[1,2]。
那么页面缓存中有什么?除了传统的磁盘支持文件之外,为了使页面缓存尽可能通用,Linux 有一些页面类型示例,它们不遵循传统磁盘支持页面的概念,但仍然存储在页面缓存。当然,如前所述,缓冲区缓存(与页缓存相同)用于存储磁盘支持的数据块。块的大小不一定与页面相同。事实上,我了解到它们可以小于页面 [3 的第 323 页]。在这种情况下,被视为缓冲区缓存一部分的页面可能由多个块组成,这些块对应于磁盘上的非连续内存区域。我不清楚缓冲区缓存中的每个页面是否必须是页面和文件之间的一对一映射,或者一个页面是否可以由来自不同文件的块组成。尽管如此,这是一种不符合原始页面缓存最严格定义的页面缓存用法。
接下来是交换缓存。正如 Barmar 在评论中提到的,匿名(非文件支持的页面)可以换出到磁盘。在磁盘和返回的过程中,页面被放入交换缓存中。交换缓存重新利用了与页面缓存类似的数据结构,特别是 address_space
结构,尽管设置了交换标志和其他一些差异 [pg. 731 of 4,5] 然而,由于交换缓存被认为是与页面缓存分开的,所以交换缓存中的匿名页面不被认为是“在页面缓存中”。
最后:关于 mmap
/malloc
是否在页面缓存中分配内存的问题。正如 [5] 中所讨论的,通常,mmap
使用来自空闲页面列表的内存,而不是页面缓存(除非我假设没有空闲页面)。当使用 mmap
映射文件以进行读写时,这些页面最终会驻留在页面缓存中。但是,对于匿名内存,mmap
/malloc
d 个页面通常不会驻留在页面缓存中。
对此的一个例外是具有特殊文件系统支持的匿名内存。例如,IPC 进程之间的共享内存 mmap
d 由基于 ram 的 tmpfs
[6] 支持。该内存位于页面缓存中,但它是匿名的,因为它没有磁盘支持文件 [pg. 600 个 4]。
来源:
- https://lwn.net/Articles/712467/
- https://www.thomas-krenn.com/en/wiki/Linux_Page_Cache_Basics
- https://www.doc-developpement-durable.org/file/Projets-informatiques/cours-&-manuels-informatiques/Linux/Linux%20Kernel%20Development,%203rd%20Edition.pdf
- https://doc.lagout.org/operating%20system%20/linux/Understanding%20Linux%20Kernel.pdf
- https://lore.kernel.org/linux-mm/20210315000738.GR2577561@casper.infradead.org/
- https://github.com/torvalds/linux/blob/master/Documentation/filesystems/tmpfs.rst