我了解虚拟内存通过显示比实际可用内存更多的内存来欺骗程序。
但是最终它必须将逻辑地址映射到实际的物理地址。现在如何增加内存?
我了解虚拟内存通过显示比实际可用内存更多的内存来欺骗程序。
但是最终它必须将逻辑地址映射到实际的物理地址。现在如何增加内存?
Answers:
它根本没有增加物理内存。它的目的完全是另外一回事。它可以做的是提供其他后备存储,以使程序可以使用比实际可用更多的内存。
虚拟内存用于将进程彼此分离和隔离,还允许将内存访问转移到其他位置。
虚拟内存允许系统为每个进程提供与其他进程隔离的自己的内存空间。由于程序可以在自己的空间中有效运行,因此它们可以完全访问整个地址空间,而不必处理可能也需要使用“相同”地址的其他程序。这具有增加可靠性和安全性的副作用,因为过程无法轻易相互干扰。
应用程序的虚拟内存空间将根据需要构建。应用程序(本身)看起来位于单个连续的内存块中,但实际上可能完全分散在物理内存中。
虚拟内存还允许捕获和转移内存访问,这使我们可以使用交换文件之类的功能。这意味着我们可以将尚未使用的部分内存推入磁盘,并设置一个指针,指出“此内存块位于文件x中的y位置”,然后可以释放物理内存。供其他应用程序使用的区域。当应用程序需要该内存时,可以从磁盘上读取它,将其放置在物理RAM的某个位置(可能与之前的位置不同),然后映射回与以前相同的虚拟内存位置。
以与使用页面文件相同的方式,虚拟内存还可以使操作系统执行有效地“延迟”加载程序共享库的操作。当主程序告诉操作系统它想使用特定的库时,操作系统可以通过检查库要求,为应用程序分配虚拟内存区域中的空间来节省时间,而不是加载整个库它可以延迟从磁盘中加载库页面,直到实际需要它们为止。这样,库中唯一要加载到RAM中的部分就是程序实际使用的部分,那些从未使用过的部分也不会被加载,因此不会浪费RAM。
使用这些技术,我们可以提高系统的稳定性,并允许更多的进程在有限的空间中运行,而不会彼此过度影响。它不是“增加内存”,而是使我们可以更有效地使用已有的东西。
交换文件是由虚拟内存系统启用,但在过去被混淆,被虚拟内存。
使用该内存时,系统必须将每个虚拟地址映射到物理地址,但并非同时使用所有内存。例如,假设浏览器中有20个选项卡,每个选项卡占用1GB的内存。在没有虚拟内存支持的操作系统中,您需要20GB的RAM才能正常工作。诀窍是,您不能同时浏览所有20个选项卡,因此具有虚拟内存的操作系统将使您能够像仅使用几GB RAM一样使用浏览器,将不活动的选项卡交换到磁盘。
虚拟内存并非专门用于交换。它的主要目的实际上是为了避免RAM碎片,这在没有虚拟内存管理的系统上是一个大问题:您可能有1GB的可用RAM,但是如果以10MB的块数提供,则请求100MB的应用程序将无法工作。
随着时间的流逝,虚拟内存会发现更多的用途,尤其是随机文件访问:如果像数据库这样的许多应用程序被迫顺序读取文件,将会变得非常缓慢,而如果操作系统允许它们假装整个文件位于(虚拟)内存,并根据访问模式优化磁盘IO和缓存。
我了解虚拟内存通过显示比实际可用内存更多的内存来欺骗程序。
虚拟内存的最初动机是提供一种比物理内存更大的地址空间的内存管理形式。
软件可以利用CPU的全部地址空间(例如2 ^ 32地址空间),而实际安装的物理内存仅为该数目的一小部分。
大型程序可以在使用虚拟内存的计算机之间移植,而无需施加巨大(已安装)的内存需求。
虚拟内存的使用可以追溯到大型机和铁氧体磁芯内存的时代(物理密度低且价格昂贵)。
但是最终它必须将逻辑地址映射到实际的物理地址。现在如何增加内存?
虚拟内存已经从一种为程序提供更多地址空间的技术发展而来。
虚拟内存是为现代操作系统中的每个进程提供安全性的关键组件,因此一个进程既不会干扰另一个进程,也不会受到另一个进程的损害。
但是与虚拟内存的多处理(不要与multiprocess ors混淆)仍然为系统提供比物理内存更多的表观内存。
每个创建的进程都提供有自己的虚拟地址空间,即自己的虚拟内存。
每个进程实际使用(并映射到虚拟内存)的物理内存量是动态的。通常,仅将包含代码(aka文本)和数据页/段以执行过程的执行的虚拟内存映射到物理内存(也称为驻留在内存中)。
非必需的代码(因为当前未执行)和数据(由于未引用/处理)都不必一直驻留在内存中。可以将代码和/或数据页面/段“交换”到后备存储(例如,HDD或SSD上的交换空间或页面文件),然后根据需要“交换(返回)”(又称“按需”) )。
虚拟内存有助于在众多进程之间高效使用有限的物理内存,每个进程都有自己的受保护的虚拟地址空间。这些虚拟内存的总和通常将大于已安装的物理内存。
现在,“增加的内存”是从系统角度来看的,而不仅仅是从程序角度来看。
虚拟内存增加了程序可以处理的数据量。从软件的角度来看,我们(通常)不在乎它们的数据存储在哪里。它可以存储在物理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指向此新的物理页面。
整个问题的关键是最大程度地减少其使用。在实践中,我们发现操作系统非常擅长选择要保留在内存中的数据以及要分页到磁盘的数据,因此绝大多数内存访问都不会引起页面错误。
虚拟内存:
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。