承诺与预留内存

问题描述 投票:0回答:1

根据“Windows Internals,第1部分”(第7版,Kindle版):

进程虚拟地址空间中的页面可以是空闲的,保留的,已提交的或可共享的。

仅关注reservedcommitted页面,第一种类型在同一本书中描述:

保留内存意味着为可能的将来使用(例如阵列)留出一系列连续的虚拟地址,同时消耗可忽略的系统资源,然后在应用程序运行时根据需要提交部分保留空间。或者,如果事先知道大小要求,则进程可以在同一函数调用中保留和提交。

保留或提交最初都会在VAD(虚拟地址描述符)中获取条目,但这两个操作都不会触及PTE(页表条目)结构。在Windows 8.1,but not anymore之前,它曾经花费PTE来预留。

如上所述,reserved意味着阻止一系列虚拟地址,而不是阻止OS级别的物理内存或页面文件空间。操作系统不会在提交限制中包含此内容,因此在分配此内存时,您可能会感到意外。值得注意的是,保留是从进程地址空间的角度进行的。这并不是说保留了任何物理资源 - 没有针对RAM空间或页面文件的“无空位”标记。

与土地的类比可能会遗漏一些东西:把reserved作为被木杆包围的土地区域,从而让其他人现在可以获得土地。但是committed怎么样?它不能是已经建造了结构(例如房屋)的土地,因为那些将需要PTE而且还没有,因为我们没有访问任何东西。只有在触摸committed数据时才会构建PTE,这将使页面可用于该过程。

主要问题是committed内存 - 至少在其初始状态 - 在功能上非常相似reserved内存。它只是在VAD中被阻挡的区域。尝试触摸其中一个地址,您将获得reserved地址的访问冲突异常:

尝试访问空闲或保留的内存会导致访问冲突异常,因为页面未映射到任何可以解析引用的存储

...以及committed的初始页面错误(紧接着是创建所需的PTE条目)。

回到土地类比,一旦房屋建成,那片土地仍然是committed。然而这有点特殊,因为当原始草在那里时仍然是committed,在第一把挖掘机开始施工之前。它类似于保留补丁的状态。也许最好把它想象成适合建筑的地形。例如,你有建造许可证(虽然你可能永远不会像那片土地上的墙一样建造)。

使用一种内存与另一种内存的原因是什么?至少有一个:操作系统保证有空间分配committed内存,如果将来会发生,但除了阻止该进程的地址空间范围外,不保证reserved内存的任何内容。 committed内存的唯一缺点是可能需要扩展一个或多个页面文件,以便能够使提交限制考虑到最近分配的块,因此请求者是否要求使用所有数据的一部分将来,操作系统可以提供对它的访问。

我真的无法想象土地类比如何能够捕捉到“保证”的细节。毕竟,reserved补丁也在物理上存在,覆盖着与其原始状态下的committed相同的草。

堆栈是另一种情况,其中reservedcommitted内存一起使用:

创建线程时,内存管理器会自动保留预定量的虚拟内存,默认情况下为1 MB。[...]虽然预留了1 MB,但只会提交堆栈的第一页[... ]以及一个警卫页面。当线程的堆栈变得足够大以触及防护页面时,会发生异常,导致尝试分配另一个防护。通过这种机制,用户堆栈不会立即消耗所有1 MB的已提交内存,而是随着需求而增长。“

有一个答案here处理为什么人们想要使用reserved记忆而不是committed。它涉及存储不断扩展的数据 - 实际上是上面描述的堆栈模型 - 并且在需要时具有特定的绝对地址范围(尽管我不确定为什么人们希望在一个过程中这样做)。

好的,我到底在问什么?

  1. 什么是reserved / committed概念的一个很好的类比?
  2. 除了上面描述的那些要求使用reserved记忆的任何其他原因?当诉诸reserved内存是一个聪明的举动时,是否有任何有趣的用例?
memory memory-management
1个回答
1
投票

您的问题取决于逻辑内存转换和虚拟内存转换之间的区别。虽然CPU文档喜欢将这两个概念混为一谈,但它们在实践中却有所不同。

如果查看逻辑内存转换,页面只有两种状态。使用您的术语,它们是免费和承诺的。空闲页面是没有映射到物理页面框架的页面,而COMMITTED页面具有这样的映射。

在虚拟存储器系统中,操作系统必须维护辅助存储器中的地址空间的副本。如何完成取决于操作系统。通常,进程将映射到几个不同的文件以进行二级存储。操作系统将地址空间划分为通常称为SECTION的内容。

例如,代码和只读数据可以虚拟地存储为可执行文件中的一个或多个SECTIONS。共享库中的代码和静态数据可以位于分页到共享库的不同部分中。您可能有一个映射到进程的共享字段,该进程使用可由多个进程访问的内存,这些进程构成另一个部分。大多数读/写数据可能位于一个或多个部分的页面文件中。操作系统如何跟踪虚拟存储每个数据部分的位置取决于系统。

对于Windows,它给出了您的一个术语的定义:可共享。可共享部分是可以将一系列地址映射到不同(或可能相同)逻辑地址的不同进程的部分。

您的上一个学期随后会保留。如果您查看Windoze VirtualAlloc功能文档,

https://docs.microsoft.com/en-us/windows/desktop/api/memoryapi/nf-memoryapi-virtualalloc

您可以看到(在您的选项中)您可以保留或提交。如果您保留,则创建一个虚拟内存部分,该部分没有映射到物理内存。

此RESERVE / COMMIT模型是特定于Windows的(尽管其他操作系统可能也会这样做)。可能的原因是节省磁盘空间。当Windoze NT开发出来时,600MB驱动器的洗衣机尺寸仍在使用中。

在64位地址空间的这些日子里,这个系统适用于(如你所说)扩展数据。理论上,堆栈溢出的异常处理程序可以简单地扩展堆栈。保留4GB内存不需要比保留单个页面更多的资源(这在32位系统中是不可行的 - 见上文)。如果您有20个线程,则可以节省堆栈空间。

什么是保留/承诺概念的一个很好的类比?

可以说RESERVE就像购买期权一样购买而COMMIT正在行使期权。

除了上面描述的那些要求使用保留内存的任何其他原因?在使用保留内存是一个聪明的举动时,是否有任何有趣的用例?

恕我直言,最有可能在没有委托的情况下保留的地方是创建堆栈和堆,而前者是最重要的。

© www.soinside.com 2019 - 2024. All rights reserved.