虚拟内存实际上是如何增加内存空间的?


70

我了解虚拟内存通过显示比实际可用内存更多的内存来欺骗程序。

但是最终它必须将逻辑地址映射到实际的物理地址。现在如何增加内存?


12
那是旧的概念。虚拟内存的最初动机是提供一种比物理内存更大的地址空间的内存管理形式。但是那时候内存是低密度且非常昂贵的。如今,使用虚拟内存的主要原因是出于过程安全性的考虑。
木屑

2
“现在如何增加内存?”。没有。该应用程序不知道系统的物理内存,它只知道虚拟内存,这就是当应用程序抱怨内存不足而正在谈论虚拟内存而不是物理内存的原因
Ramhound

2
请记住,虚拟内存系统非常聪明。如果n个进程具有相同的只读页,则所有n个进程可以使用同一页的物理内存。
埃里克·利珀特

65
不要将虚拟内存视为愚弄任何东西。 内存是存储和检索数据的抽象能力。虚拟内存为该抽象提供了一种实现。该抽象的某些部分由RAM支持,而某些部分则由磁盘支持,这是该抽象的实现细节。
埃里克·利珀特

4
@HagenvonEitzen除了最初从磁盘读取的页面之外,不确定如何在磁盘上“始终”使用内存,除非将页面换出,否则其内容可能永远不会在磁盘上,这尤其适用于固定在内存中的页面,例如由于对内核功能至关重要。
迈克尔(Michael)

Answers:


116

它根本没有增加物理内存。它的目的完全是另外一回事。它可以做的是提供其他后备存储,以使程序可以使用比实际可用更多的内存。

虚拟内存用于将进程彼此分离和隔离,还允许将内存访问转移到其他位置。

虚拟内存允许系统为每个进程提供与其他进程隔离的自己的内存空间。由于程序可以在自己的空间中有效运行,因此它们可以完全访问整个地址空间,而不必处理可能也需要使用“相同”地址的其他程序。这具有增加可靠性和安全性的副作用,因为过程无法轻易相互干扰。

应用程序的虚拟内存空间将根据需要构建。应用程序(本身)看起来位于单个连续的内存块中,但实际上可能完全分散在物理内存中。

虚拟内存还允许捕获和转移内存访问,这使我们可以使用交换文件之类的功能。这意味着我们可以将尚未使用的部分内存推入磁盘,并设置一个指针,指出“此内存块位于文件x中的y位置”,然后可以释放物理内存。供其他应用程序使用的区域。当应用程序需要该内存时,可以从磁盘上读取它,将其放置在物理RAM的某个位置(可能与之前的位置不同),然后映射回与以前相同的虚拟内存位置。

以与使用页面文件相同的方式,虚拟内存还可以使操作系统执行有效地“延迟”加载程序共享库的操作。当主程序告诉操作系统它想使用特定的库时,操作系统可以通过检查库要求,为应用程序分配虚拟内存区域中的空间来节省时间,而不是加载整个库它可以延迟从磁盘中加载库页面,直到实际需要它们为止。这样,库中唯一要加载到RAM中的部分就是程序实际使用的部分,那些从未使用过的部分也不会被加载,因此不会浪费RAM。

使用这些技术,我们可以提高系统的稳定性,并允许更多的进程在有限的空间中运行,而不会彼此过度影响。它不是“增加内存”,而是使我们可以更有效地使用已有的东西。

交换文件是由虚拟内存系统启用,但在过去被混淆,虚拟内存。


评论不作进一步讨论;此对话已转移至聊天
Sathyajith Bhat

21

莱曼的解释

使用该内存时,系统必须将每个虚拟地址映射到物理地址,但并非同时使用所有内存。例如,假设浏览器中有20个选项卡,每个选项卡占用1GB的内存。在没有虚拟内存支持的操作系统中,您需要20GB的RAM才能正常工作。诀窍是,您不能同时浏览所有20个选项卡,因此具有虚拟内存的操作系统将使您能够像仅使用几GB RAM一样使用浏览器,将不活动的选项卡交换到磁盘。

更复杂的方面

虚拟内存并非专门用于交换。它的主要目的实际上是为了避免RAM碎片,这在没有虚拟内存管理的系统上是一个大问题:您可能有1GB的可用RAM,但是如果以10MB的块数提供,则请求100MB的应用程序将无法工作。

随着时间的流逝,虚拟内存会发现更多的用途,尤其是随机文件访问:如果像数据库这样的许多应用程序被迫顺序读取文件,将会变得非常缓慢,而如果操作系统允许它们假装整个文件位于(虚拟)内存,并根据访问模式优化磁盘IO和缓存。


9
很遗憾,我们生活在一个每个浏览器选项卡都需要1GB内存的世界中
tbodt

9
@tbodt我怪古埃及人。如果他们能通过驯养那些讨厌的猫而知道自己在做什么!
德米特里·格里戈里耶夫

@tbodt也有点夸张。打开8个标签的浏览器仅占用500MB的内存。
Random832 '17

2
@ Random832当然,这是一种夸张,尽管我不确定夸张和适应未来之间的界限。我的第一台PC拥有32 MB的RAM,我可以轻松地在Opera中打开8个选项卡而无需进行明显的交换。现在它需要500MB,因此再过20年它可能会达到8GB。
德米特里·格里戈里耶夫

5

从实际添加更多主内存硬件的意义上讲,虚拟内存不会增加内存。但是它可以增加可用地址的范围。因此,可以有一个由代码段和数据(堆栈和堆)段组成的正在运行的程序,并且这两个程序都可能占用一个虚拟地址范围,该范围大于该虚拟机物理上实际存储空间所提供的物理地址范围。机。诀窍在于,任何时候这些虚拟地址中只有一小部分由物理主内存支持[但是所有内容最终都由磁盘存储支持]。这是因为引用局部性现象:在任何时候,仅执行程序段的一个或多个小连续部分中的指令,并且仅对数据段的一个或多个小连续部分中的数据进行操作[当然,行为实际上更加复杂,但大部分时间确实遵循此模式]


4

我了解虚拟内存通过显示比实际可用内存更多的内存来欺骗程序。

虚拟内存的最初动机是提供一种比物理内存更大的地址空间的内存管理形式。
软件可以利用CPU的全部地址空间(例如2 ^ 32地址空间),而实际安装的物理内存仅为该数目的一小部分。
大型程序可以在使用虚拟内存的计算机之间移植,而无需施加巨大(已安装)的内存需求。
虚拟内存的使用可以追溯到大型机和铁氧体磁芯内存的时代(物理密度低且价格昂贵)。

但是最终它必须将逻辑地址映射到实际的物理地址。现在如何增加内存?

虚拟内存已经从一种为程序提供更多地址空间的技术发展而来。
虚拟内存是为现代操作系统中的每个进程提供安全性的关键组件,因此一个进程既不会干扰另一个进程,也不会受到另一个进程的损害。
但是与虚拟内存的多处理(不要与multiprocess ors混淆)仍然为系统提供比物理内存更多的表观内存。

每个创建的进程都提供有自己的虚拟地址空间,即自己的虚拟内存。
每个进程实际使用(并映射到虚拟内存)的物理内存量是动态的。通常,仅将包含代码(aka文本)和数据页/段以执行过程的执行的虚拟内存映射到物理内存(也称为驻留在内存中)。

非必需的代码(因为当前未执行)和数据(由于未引用/处理)都不必一直驻留在内存中。可以将代码和/或数据页面/段“交换”到后备存储(例如,HDD或SSD上的交换空间或页面文件),然后根据需要“交换(返回)”(又称“按需”) )。

虚拟内存有助于在众多进程之间高效使用有限的物理内存,每个进程都有自己的受保护的虚拟地址空间。这些虚拟内存的总和通常将大于已安装的物理内存。
现在,“增加的内存”是从系统角度来看的,而不仅仅是从程序角度来看。


3

虚拟内存增加了程序可以处理的数据量。从软件的角度来看,我们(通常)不在乎它们的数据存储在哪里。它可以存储在物理DRAM内存中,也可以存储在插入计算机的闪存驱动器中,甚至可以存储在旋转的磁盘上。该软件关心的是,当它要求访问该数据时,它会成功。

实际上,我们还希望程序能够快速运行。对于速度的考虑,我们做护理,其中数据。我们希望将最常访问的数据存储在允许最快访问的硬件中。我们的方案将希望完全耗尽的DRAM。但是,我们通常没有足够的DRAM来执行此操作。虚拟内存是一种解决方案。

使用虚拟内存,操作系统可以“调出”一段时间内未使用的数据,并将其存储在硬盘上。这仍然可以访问,只是速度很慢。如果程序请求硬盘上的数据,则操作系统必须花时间从磁盘上读取数据,然后将其移回DRAM。

从理论上讲,它可以直接从磁盘读取数据。但是,有理由不这样做。这些程序不想知道所有这些复杂情况。我们可以并且确实编写了将数据智能地放入磁盘的软件(称为缓存)。但是,这需要大量的额外工作。我们可以用代码执行的最快速度是:

if data is not in memory
    read data from disk into memory
operate on data

精明的读者会注意到,即使数据在内存中,我们也必须有条件检查其是否存在。这比直接在内存中运行要慢得多!

虚拟内存通过在CPU上进行硬件检查来解决此问题。CPU可以非常快速地执行此虚拟内存操作,因为它可以将硬件专用于此。任何单独在软件中执行此操作的尝试都必须使用CPU的通用部分,这些部分自然比专用晶体管要慢。

这导致为什么我们总是将数据分页回内存,而不仅仅是从磁盘读取数据并留在那儿。我们将内存分为“页面”,每个页面都标记为内存中存在或不存在。操作系统以便于CPU直接使用的格式维护该表。每当程序访问存在的数据时,CPU上的硬件就会使他们直接访问DRAM中的数据。当数据不存在时,将发出“页面错误”,告诉操作系统将磁盘上的该页面从磁盘加载到内存的某个物理页面,并更新表以将CPU指向此新的物理页面。

整个问题的关键是最大程度地减少其使用。在实践中,我们发现操作系统非常擅长选择要保留在内存中的数据以及要分页到磁盘的数据,因此绝大多数内存访问都不会引起页面错误。


2

它通过使地图项成为临时项来实现。

当程序访问逻辑地址时,CPU在映射中查找对应的物理地址。如果找到,则内存访问将按预期进行;否则,将继续进行内存访问。如果找不到,则必须分配一个物理地址,并从其他存储(“交换空间”)中加载内容。如果已经将每个物理地址分配给某个逻辑地址,则必须“交换掉”某些逻辑地址(它们的内容保存回交换空间),以使物理地址可用。

分配的最大内存是交换空间的大小,它可能比已安装的内存大得多。将交换空间视为“实际”内存,将RAM视为交换空间的高速缓存可能会有所帮助。

(这远不是一个详尽的描述,它旨在回答紧迫的问题而不涉及相关但不必要的细节。)


1

基本概念依赖于以下事实:现代CPU可以管理转换表,以跟踪“已分配了要使用的特定地址范围以及哪些物理地址(请考虑内存总线上的A00..Axx行)”(如果有) ,目前用于实际存储数据。因为“根本没有”是可能的并且可以接受的状态:“如果存在”:在这种情况下,错误条件(所谓的“页面错误”)将在硬件级别上产生-并且此错误将触发操作系统级别的处理程序,该处理程序可以例如将已写入交换文件的内存内容加载回物理内存中的任何空闲位置(如果读取),或找到实际位置以放置内容(在写入的情况下),更新上述翻译表,并且只有然后将手控制权移回到试图访问该内存的过程中,这将不会更明智。


1

虚拟内存:

1)允许将较大的虚拟地址空间映射到更少量的物理内存,而多余的“交换”到磁盘或SSD,或者预期地“交换”到NVRAM和其他设备。

2)允许将较大的虚拟地址空间(例如64位)映射到较小的物理地址空间(例如32或64位)

3)允许将较小的虚拟地址空间(例如32位)映射到较大的物理地址空间(例如40位),从而允许较旧的应用程序利用更多的物理DRAM。

4)允许我们在物理地址空间中零散且不连续的物理内存在虚拟地址空间中连续。

5)允许为进程分配自己的虚拟地址空间,从而使进程彼此隔离。

6)允许碰巧共享相同数据值的不同虚拟地址分配给单个物理页面。

这可以在单个进程或OS中发生-大多数BSD UNIX派生的OS具有单个零的只读页面,该页面可以映射到任何零填充的虚拟页面,通常为COW(写时复制-只读零,被捕获的写入和页面未共享且可写)。

它可能在进程之间发生-例如UNIX fork()创建以COW方式共享几乎所有虚拟内存的子进程。

它可能在操作系统之间发生-例如,虚拟机主机上的来宾操作系统可能具有重复数据删除页面,共享的COW等。(一些近期的安全攻击已利用了这一点。)

7)虚拟内存可以允许将虚拟地址空间的一部分映射到文件,或者映射到其他处理器上映射的内存,无论是在同一多处理器系统中还是跨Internet。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.