linux - 匿名内存是 Linux 上页面缓存的一部分吗?
问题描述
匿名内存- 即程序堆和堆栈 - 是 Linux 上页面缓存的一部分吗?内核的链接文档没有说明这一点。
但是关于页面缓存的维基百科条目包含一个图形(看右上角),它给我的印象是malloc()在页面缓存中分配动态内存:
那有意义吗?关于mmap()
,当它用于访问文件时,使用页面缓存是有意义的。通常也用于匿名内存,例如malloc()
和匿名映射通过mmap()
?
我会很感激一些解释。
谢谢你。
编辑 2021-03-14
我决定最好在他们的邮件列表上询问内存子系统的内核维护者。幸运的是, Matthew Wilcox回应并帮助了我。提炼:
- 匿名内存不由
page cache
. - 匿名页面有多种不同的处理方式——它们可以在
LRU lists
(最近最少使用)上找到,也可以通过page tables
. 有点特设。 - 维基百科的图表是错误的。它包含进一步的缺陷。
- 如果系统提供交换并且如果匿名内存被交换 - 它进入
swap cache
,而不是page cache
.
解决方案
TLDR:不,除了具有特殊文件系统支持的匿名内存(如 IPC shmem)。
更新:更正答案以合并来自与 OP的内核邮件列表讨论的新信息。
页面缓存最初旨在成为操作系统级别的内存区域,用于快速查找磁盘支持的文件,其原始形式是缓冲区缓存(用于缓存磁盘中的块)。页面缓存的概念出现在 1995 年晚些时候 Linux 诞生之后,但前提是相似的,只是一个新的抽象——页面 [ 1 ]。事实上,最终两个缓存合而为一:页缓存包括缓冲区缓存,或者更确切地说,缓冲区缓存是页缓存[ 1 , 2 ]。
那么页面缓存中的内容是什么?除了传统的磁盘支持文件之外,为了使页面缓存尽可能通用,Linux 提供了一些不符合传统磁盘支持页面概念的页面类型示例,但仍存储在页面缓存。当然,如前所述,缓冲区缓存(与页面缓存相同)用于存储磁盘支持的数据块。块不一定与页面大小相同。事实上,我了解到它们可以小于页面 [pg.323 of 3]。在这种情况下,被视为缓冲区高速缓存一部分的页面可能由多个块组成,这些块对应于磁盘上的非连续内存区域。那么,我不清楚缓冲区缓存中的每个页面是否必须是页面和文件之间的一对一映射,或者一个页面是否可以包含来自不同文件的块。尽管如此,这是一种不遵守原始页面缓存最严格定义的页面缓存用法。
接下来是交换缓存。正如 Barmar 在评论中提到的,匿名(非文件支持的页面)可以换出到磁盘。在到磁盘和返回的过程中,页面被放入交换缓存中。交换缓存重新利用与页面缓存类似的数据结构,特别是address_space
结构,尽管设置了交换标志和一些其他差异 [pg. 731 of 4 , 5 ] 但是,由于交换缓存被认为与页面缓存分开,因此交换缓存中的匿名页面不被视为“在页面缓存中”。
最后:关于是否mmap
/是否malloc
在页面缓存中分配内存的问题。正如 [ 5 ] 中所讨论的,通常mmap
使用来自空闲页面列表的内存,而不是页面缓存(除非没有剩余的空闲页面,我假设)。当使用mmap
映射文件进行读写时,这些页面最终会驻留在页面缓存中。但是,对于匿名内存,mmap
/ malloc
d 页通常不驻留在页缓存中。
一个例外是具有特殊文件系统支持的匿名内存。例如,mmap
IPC 进程之间的共享内存 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
推荐阅读
- c++ - 如何在 Linux 的 Visual Studio Code 中链接 SFML 库?
- javascript - Alasql - 单个 promise 语句中的多个 sheetid
- java - 如何在 Comparator 的 compare() 方法中更改变量值
- java - Xamarin Android:LinearLayout 背景和 Drawable Left 无法正确显示
- java - 来自外部 API 的“无法反序列化实例”
- javascript - 为什么白名单不会出现错误模型 NestJs 的错误
- c# - 将 Object 转换为泛型类型。对象必须实现 IConvertible
- java - 将自定义属性文件转换为java中的复杂类型对象
- scala - 对 csv 数据应用逻辑回归时出现问题
- r - 如何遍历多个txt文件并将内容写入数据框