首页 > 编程知识 正文

超出物理内存机制的设备,内存已超标

时间:2023-05-06 05:48:27 阅读:245985 作者:1311

到目前为止,我们假定地址空间是不实际的小的,并且适合于物理内存。事实上,我们一直假设每个运行过程的每个地址空间都适合内存。现在,我们将放松这些大的假设,并假设我们希望支持许多并发运行的大型地址空间。为此,我们需要在内存层次结构中增加一个级别。到目前为止,我们假定所有页面都驻留在物理内存中。但是,为了支持大的地址空间,操作系统需要一个地方来存储当前不太需要的地址空间的部分。一般来说,这样一个位置的特点是它应该比记忆容量更大;因此,它通常是比较慢的(如果它更快,我们就只把它当作内存,不是吗?)在现代系统中,这个角色通常由硬盘驱动。在现代系统中,这个角色通常由硬盘驱动。因此,在我们的内存层次结构中,大而慢的硬盘驱动器位于底部,内存就在上面。因此,我们到达了问题的症结所在。问题的关键是:如何超越物理内存,操作系统如何使用更大、更慢的设备来透明地提供虚拟地址空间的幻象。

您可能有一个问题:为什么我们要支持一个进程的单个大地址空间?再一次,答案是方便和易用性。有了一个大的地址空间,你不必担心你的程序的数据结构是否有足够的内存空间;相反,您只需要自然地编写程序,根据需要分配内存。这是一个强大的幻觉,OS提供,并且使你的生活更简单。你欢迎!在使用内存覆盖的旧系统中发现了一个对比,这需要程序员在需要的时候手动地将代码或数据移动到内存中(D97)。试着想象一下这将会是什么样子:在调用一个函数或访问一些数据之前,您需要首先安排代码或数据在内存中;令人反感的。

旁白:存储技术

我们将更深入地研究I/O设备的实际工作原理(参见关于I/O设备的章节)。所以要有耐心!当然,速度较慢的设备不一定是硬盘,但可能是更现代的东西,比如基于闪存的SSD。我们也会讨论这些事情。现在,假设我们有一个大的、相对慢的设备,我们可以用它来帮助我们构建一个非常大的虚拟内存的假象,甚至比物理内存本身还要大。

除了单个进程之外,交换空间的添加还允许操作系统支持多个并发运行进程的大型虚拟内存的幻象。多程序设计(同时运行多个程序,以便更好地利用机器)的发明几乎要求能够交换一些页面,因为早期的机器显然不能同时容纳所有进程所需的所有页面。因此,多编程和易用性的结合使我们想要支持使用比物理可用的更多的内存。这是所有现代虚拟机系统都有的功能;现在,我们将会学到更多的东西。

21.1交换空间

我们需要做的第一件事是在磁盘上预留一些空间来来回移动页面。在操作系统中,我们通常将这样的空间称为交换空间,因为我们将页面从内存中交换到它,并将其交换到内存中。因此,我们将简单地假设操作系统可以从页面大小的单元中读取并写入交换空间。要做到这一点,操作系统需要记住给定页面的磁盘地址。

交换空间的大小很重要,因为它最终决定了系统在给定时间内可以使用的最大内存分页数。简单起见,我们假设它现在非常大。在这个小示例中(图21.1),您可以看到一个4页物理内存和8页交换空间的小示例。在示例中,三个进程(Proc 0、Proc 1和Proc 2)正在积极地共享物理内存;然而,这三者中的每一个都只在内存中有一些有效的页面,其余的都位于磁盘上的交换空间中。第四个进程(Proc 3)将其所有的页面交换到磁盘,因此显然不是当前运行的。其中一个交换区仍然是释放的。甚至在这个小例子中,希望您可以看到使用交换空间如何让系统假装内存比实际的要大。我们应该注意,交换空间并不是交换流量的唯一磁盘位置。例如,假设您正在运行一个程序二进制文件(例如,ls,或您自己编译的主程序)。从这个二进制文件中的代码页最初在磁盘上找到,当程序运行时,它们会被加载到内存中(当程序开始执行时,所有的代码都被加载到内存中)。从这个二进制文件中的代码页最初在磁盘上找到,当程序运行时,它们会被加载到内存中(当程序开始执行时,所有的代码都被加载到内存中)。但是,如果系统需要在物理内存中为其他需要腾出空间,那么它可以安全地重用这些代码页的内存空间,因为它知道以后可以从文件系统中的on-disk二进制文件中再次交换它们。


21.2当前位

现在我们在磁盘上有了一些空间,我们需要在系统中增加一些机器,以支持从磁盘交换页面。为了简单起见,让我们假设我们有一个带有硬件管理的TLB的系统。首先回想一下在内存引用上发生的事情。运行过程生成虚拟内存引用(用于指令获取或数据访问),在这种情况下,硬件将它们转换为物理地址,然后从内存中获取所需的数据。请记住,硬件首先从虚拟地址提取VPN,检查TLB是否匹配(TLB命中),如果命中,则产生相应的物理地址并从内存中获取。这是常见的情况,因为它是快速的(不需要额外的内存访问)。如果在TLB中未找到VPN(即:在内存中(使用页表基寄存器),硬件在内存中定位页表,并使用VPN作为索引查找该页面的页表条目(PTE)。如果页面在物理内存中是有效的,那么硬件从PTE中提取PFN,在TLB中安装它,并重试指令,这一次生成TLB命中;到目前为止还好。

但是,如果我们希望允许将页面交换到磁盘,那么我们必须添加更多的机器。具体地说,当硬件在PTE中查找时,它可能会发现页面在物理内存中不存在。硬件(或软件管理的TLB方法中的操作系统)的方式决定了这是通过每个页表条目中的新信息,即当前位。如果将当前位设置为1,则表示该页面存在于物理内存中,所有的内容都是如上所述;如果将其设置为零,那么该页面不是在内存中,而是在某个地方的磁盘上。:访问不属于物理内存的页面的行为通常被称为页面错误。

旁白:交换术语和其他东西

例如,一个页面错误通常可以引用到生成某种错误的页表的任何引用:这可能包括我们在这里讨论的错误类型,即。,一个页面不存在的错误,但有时可以指非法的内存访问。实际上,我们把绝对合法的访问(映射到一个进程的虚拟地址空间,但根本不在物理内存中)是一个错误,这是很奇怪的。实际上,它应该被称为页面错误,但是通常,当人们说一个程序是页面错误时,他们的意思是它正在访问它的虚拟地址空间的一部分,而这个虚拟地址空间是操作系统交换到磁盘上的。

我们怀疑这种行为被称为故障的原因与操作系统中的机器有关。当swdzx事情发生时,即当硬件不知道如何处理时,硬件只是将控制转移到操作系统,希望它能使事情变得更好。:在这种情况下,进程希望访问的页面从内存中丢失;硬件只做它能做的事情,那就是引发异常,操作系统从那里接管。由于这与流程执行非法操作时发生的情况相同,所以我们将活动称为错误也就不足为奇了。

在页面错误上,操作系统被调用来服务页面错误。正如我们现在所描述的,特定的一段代码,即页面错误处理程序,运行,并且必须服务于页面错误。

21.3的页面错误。

回想一下TLB的缺失,我们有两种类型的系统:hardwaremanage TLBs(硬件在页面表中查找所需的翻译)和软件管理的TLBs(操作系统在那里)。在这两种类型的系统中,如果一个页面不存在,操作系统将负责处理页面错误。这个名为OS page-fault handler的专用程序运行来决定要做什么。几乎所有系统都处理软件中的页面错误;即使使用硬件管理的TLB,硬件也信任操作系统来管理这一重要的任务。

如果一个页面不存在并且已经被交换到磁盘,操作系统将需要将页面交换到内存中以服务页面错误。因此,出现了一个问题:操作系统如何知道在哪里找到所需的页面。在许多系统中,页表是存储这些信息的自然场所。因此,操作系统可以使用PTE中通常用于数据的位,例如磁盘地址的PFN。当操作系统接收到一个页面的页面错误时,它会在PTE中查找地址,并将请求发送到磁盘,以将页面读取到内存中。

旁白:为什么硬件不能处理页面错误。我们从TLB的经验得知,硬件设计师不愿意相信操作系统可以做很多事情。那么,他们为什么要信任操作系统来处理页面错误呢?有几个主要原因。首先,页面错误到磁盘的速度很慢;即使操作系统需要很长时间来处理一个错误,执行大量指令,磁盘操作本身通常是非常缓慢的,运行软件的额外开销是最小的。其次,为了能够处理一个页面错误,硬件必须理解交换空间,如何向磁盘发出I/Os,以及其他当前不太了解的其他细节。因此,出于性能和简单性的原因,操作系统处理页面错误,甚至硬件类型也可以是快乐的。

当磁盘I/O完成时,操作系统将更新页表以标记当前页,更新页表条目的PFN字段(PTE),记录新取的页面的内存位置,并重试该指令。接下来的尝试可能会生成一个TLB miss,然后用翻译服务并更新TLB(在服务页面错误时,可以交替更新TLB以避免这一步)。最后,最后一次重新启动将在TLB中找到转换,从而在转换的物理地址中从内存中获取所需的数据或指令。

注意,当I/O处于飞行状态时,进程将处于被阻塞状态。因此,当页面错误被服务时,操作系统将可以自由地运行其他已准备好的进程。因为I/O非常昂贵,所以一个进程的I/O(页面错误)和另一个进程的执行的重叠是一个多程序系统能够最有效地使用其硬件的另一种方式。

21.4如果内存满了怎么办?

上述过程中,您可能会注意到,我们假设有足够的空闲内存的页交换空间的一个页面。

在上述过程中,您可能会注意到,我们假设是足够的空闲内存页面交换空间的一个页面。当然,这可能并非如此;记忆可能完全(或接近)。因此,操作系统可能会喜欢第一页一个或多个页面来腾出空间新页面(s)操作系统的引进。选择的过程页面踢出去,或替换被称为页面置换政策。

事实证明,很多想法都被投入到创建一个良好的页面布局策略中,因为踢出错误的页面可以让程序性能付出巨大的代价。做出错误的决定会导致程序以磁盘般的速度运行,而不是像内存一样的速度;在目前的技术中,这意味着一个程序可以运行1万或10万倍的速度。因此,这样的政策是我们应该详细研究的。事实上,这正是我们在下一章所要做的。就目前而言,了解这种政策的存在是很好的,它建立在这里所描述的机制之上。






21.5页故障控制流程。

有了所有这些知识,我们现在可以粗略地描绘出内存访问的完全控制流。换句话说,当有人问你程序从内存中获取一些数据时会发生什么?你应该对所有的可能性都有一个很好的想法。参见图21.2和21.3中的控制流,了解更多细节;第一个图显示了在翻译过程中硬件所做的工作,以及操作系统在页面错误上做了什么。从图21.2的硬件控制流程图中,注意到现在有三个重要的案例可以理解TLB缺失。第一,这一页是现在和有效的(第18行第21行);在这种情况下,TLB错误处理程序可以简单地从PTE中获取PFN,重试指令(这一次会导致TLB命中),从而继续像以前描述的那样(多次)。在第二种情况(第22条23行)中,必须运行页面错误处理程序;尽管这是一个合法的访问过程页面(毕竟它是有效的),但它并不存在于物理内存中。第三(最后),访问可能是一个无效页面,例如程序中的一个bug(第13行14行)。在这种情况下,PTE中没有其他的位真的很重要;硬件捕获了这个无效的访问,并且OS陷阱处理程序运行,可能会终止这个过程。从图21.3的软件控制流中,我们可以看到操作系统为了服务页面错误所必须做的事情。首先,操作系统必须找到一个物理框架,以便在页面中存在即将被发现的错误;如果没有这样的页面,我们将不得不等待替换算法运行并将一些页面踢出内存,从而使它们在这里使用。


在实际的框架中,处理程序会发出I/O请求,以从交换空间中读取页面。最后,当这个缓慢的操作完成时,操作系统会更新页表并重试指令。重试将导致TLB失误,然后在另一次重试时,TLB命中,这时硬件将能够访问所需的项。

21.6当替换真的发生时。

到目前为止,我们描述替换发生的方式是假设OS一直等到内存完全满了,然后才替换(收回)一个页面,为其他页面腾出空间。可以想象,这有点不现实,操作系统有很多原因使内存的一小部分能够更主动地保留。为了保持少量的内存,大多数操作系统都有一些高水印(HW)和低水印(LW)来帮助决定何时开始从内存中删除页面。其工作原理如下:当操作系统注意到有少于LW页面可用时,一个负责释放内存的后台线程运行。线程会将页面驱逐到可用的HW页面。后台线程,有时称为交换守护进程或page daemon1,然后进入休眠状态,很高兴它释放了一些运行进程和操作系统的内存。通过一次执行多个替换,新的性能优化成为可能。例如,许多系统会将多个页面集群或分组,并立即将它们写入交换分区,从而提高磁盘的效率[LL82];稍后我们将在更详细的讨论磁盘时看到,这种集群减少了磁盘的查找和旋转开销,从而显著地提高了性能。为了处理后台的分页线程,应该稍微修改图21.3中的控制流;该算法不直接执行替换,而是简单地检查是否有可用的空闲页面。如果没有,它将会通知后台的分页线程,这些页面是需要的;当线程释放一些页面时,它将重新唤醒原来的线程,它可以在所需的页面中页面并进行工作。

小贴士:在后台工作。悲凉的小懒猪有一些工作要做的时候,最好在后台做一下,以提高效率,并允许分组操作。操作系统通常在后台工作;例如,在实际将数据写入磁盘之前,许多系统缓冲文件在内存中写入。这样做有许多可能的好处:磁盘效率提高了,因为磁盘现在可以同时接收许多写操作,因此可以更好地调度它们;提高了写的延迟,因为应用程序认为写完成得相当快;减少工作的可能性,因为写入可能永远不需要到磁盘上(也就是。,如果文件被删除);更好地利用空闲时间,因为当系统处于空闲状态时,可能会完成后台工作,从而更好地利用硬件[G+95].

21.7总结.

在这个简短的章节中,我们介绍了访问更多内存的概念,而不是系统内的物理存在。要做到这一点,在页表结构中需要更复杂的内容,因为必须包含一个当前位(某种类型)来告诉我们页面是否存在于内存中。当不这样做时,操作系统的页面错误处理程序会运行来服务页面错误,从而安排将所需的页面从磁盘转移到内存中,可能首先在内存中替换一些页面,为那些即将被交换的页面腾出空间。回想一下,重要的是(令人惊讶的是!),这些操作都是透明地进行的。就流程而言,它只是访问它自己的私有的、连续的虚拟内存。在幕后,页面被放置在物理内存中的任意(非连续的)位置,有时甚至不存在于内存中,需要从磁盘获取。虽然我们希望在常见的情况下,内存访问是快速的,但在某些情况下,它需要多个磁盘操作来服务它;在最坏的情况下,在最坏的情况下,需要花费许多毫秒来完成。



版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。