什么是惰性交换预留?

什么是惰性交换预留?

我正在读Linux 编程接口

49.9MAP_NORESERVE 和交换空间过度使用

某些应用程序创建大型(通常是私有匿名)映射,但仅使用映射区域的一小部分。例如,某些类型的科学应用程序分配一个非常大的数组,但仅对数组中几个相距较远的元素进行操作(所谓的稀疏数组)。

如果内核总是为整个此类映射分配(或保留)足够的交换空间,则可能会浪费大量交换空间。相反,内核可以仅在实际需要时(即,当应用程序访问页面时)为映射的页面保留交换空间。这种方法称为惰性交换预留,并且具有应用程序使用的总虚拟内存可以超过 RAM 加上交换空间的总大小的优点。

换句话说,惰性交换预留允许过度使用交换空间。只要所有进程不尝试访问其映射的整个范围,这种方法就可以正常工作。 ...

据我所知,交换空间是磁盘中的一块空间,保留用于内存交换。当内存中的这些页面处于非活动状态时,它们会被交换到交换空间在磁盘中。它就像内存/RAM 的二级缓存。

那这到底是什么惰性交换预留机制?

让我用一个例子来证明我的困惑。

  1. 一些应用程序创建大型(通常是私有匿名)映射......

好吧,然后假设我有malloc一个大数组16384(4096*4)字节(创建大(通常是私有匿名)映射),并且仅对数组​​中几个广泛分离的元素进行操作。

然后一些不活动的页面被交换到交换空间,对吗?假设0-4095(4096B),8192-12287(4096B)位于内存中,所有其他非活动页面 ,4096-8191(4096B)12288-16383(4096B)交换到交换空间中。

那么这句话是什么意思呢:

相反,内核可以仅在实际需要时(即,当应用程序访问页面时)为映射的页面保留交换空间。

这些非活动页面(4096-8191(4096B)12288-16383(4096B))如果不停留在交换空间?文本似乎表明有一个用于交换空间的第三级缓存。

memory -> swap space (disk) -> ????

答案1

Swap 并不是真正的内存二级缓存;它是内存的几个后备存储之一。当内核需要分配一页物理内存,但没有足够的可用内存时,需要逐出另一页;只有当被逐出页面的内容是可丢弃的或者可以从其他地方恢复时,它才能做到这一点。其他地方是后备存储:它可以是磁盘上的文件(例如对于可执行文件或映射文件),或交换的某些区域。

交换预订当内存核算跟踪过度使用时,就会发挥作用(参见表 49-4)LPI)。当不允许过度使用时,内核需要在分配时确定是否可以进行分配。对于私有可写映射和共享匿名映射,这意味着它必须有足够的地址空间,以及足够的交换空间(这样内核才能保证映射内存的内容可以写入那里,从而保证写入映射内存永远不会导致SIGSEGV)。

过度使用需要延迟交换预留:这意味着内核可以分配交换支持的内存映射,而无需预留相应的交换空间。正如中提到的LPI,这允许程序分配比实际可用的内存多得多的内存,并且应该使用 来请求MAP_NORESERVE。然后,保留仅在写入页面时发生,这意味着写入可能会失败,SIGSEGV并导致 OOM 杀手介入。

对于比 16KiB 示例大得多的分配,这变得很重要。想象一下,您想要一个稀疏的 64GiB、262,144×262,144 数组,以使您的程序更易于编写:在严格保留的情况下,您需要拥有所有可用内存;如果没有严格的保留,您不会,并且只有您写入的页面才会真正被分配。

请注意,这都是 Linux 特定的,并且与所选系统过度使用策略 ( /proc/sys/vm/overcommit_memory) 紧密相关:在模式 1(始终过度使用)和 2(从不过度使用)中,MAP_NORESERVE不会改变任何内容,它仅在模式 0 中有效。

答案2

交换空间是磁盘中的一块空间

一块什么样的空间?虚拟内存。

内核很容易为每个进程提供所需的虚拟内存。这就是懒惰、过度投入的部分。的例子是稀疏科学数组想要表明懒惰往往是个好主意。整个数组不会立即使用,因此其他程序可以同时运行。

它就像内存/RAM 的二级缓存。

但大多数时候并不比“那个”磁盘快(没有专用的交换设备)

恰恰相反,尤其是在过度承诺的情况下:

交换将(物理)RAM 转变为存储设备的缓存。

(即RAM不是进程所拥有和保存的东西,但它是每个进程的活动页面(包括映射文件)的工作区域)。


这里涉及的是交换空间的过度使用,而不仅仅是 RAM。不管有没有交换,过量使用后都可能导致 OOM 的情况。

相关内容