操作系统导论-内存篇3

明明记得分页已经写过了,怎么找不到了,继续操作系统导论。到目前为止,我们讨论的地址空间都非常小,能够放入物理内存中。事实上,我们假设每个正在运行的进程的地址空间都是放入在内存中。这一篇里,我们放开这些假设,并且假设我们需要支持更多同时运行的巨大地址空间。

为了达到这个目的,我们需要在内存层级上再加一层。为了支持更大的地址空间,操作系统需要把当前没有在用的那部分地址空间找个地方存起来。一般来说,这个地方有一个特点,那就是比内存有更大的容量。因此,一般来说也会更慢。那我们的关键问题就是:

操作系统如何利用大而慢的设备,透明的提供巨大虚拟地址空间的假象。

那么为什么我们需要支持巨大的地址空间?答案是方便和易用性。有了巨大的地址空间,我们就不必在担心数据结构是否足够空间存储,只需要自然的编写程序,根据需要分配内存即可。在早期的系统使用”内存覆盖“,还需要手动移入、移出内存中的代码或者数据,在访问某些数据之前,还需要先安排将代码或数据转入内存。

我们要做的第一件事情,就是在磁盘上开辟一块空间用于物理页的移入和移出。在操作系统中,这样的空间叫做交换空间(swap space),因为我们将内存中的页交换到其中,在需要的时候又交换回去。因此,我们需要操作系统能够以页大小为单元读取或写入交换空间,为了达到这个目的,操作系统需要记录给定页的磁盘地址。

我们需要注意,交换空间不是唯一的磁盘交换目的地。假设我们运行一段程序,这段代码最开始是在磁盘上的,但是程序运行时,他被加载到内存中,如果操作系统需要在物理内存中腾出一些空间,则可以安全的重新使用这些代码页的内存空间,因为稍后需要它时又可以从磁盘上加载进来。

我们回想一下内存引用发生了什么。硬件首先从虚拟地址中获得虚拟页号,检查TLB是否命中,如果命中,则获取物理地址并从内存中取回。如果TLB未命中,即找不到虚拟页号,则硬件在内存中查找页表,通过虚拟页号查找到页表项,如果页有效并且存在于物理内存中,则硬件从页表项中获取物理帧号,然后插入到TLB中,再次重试该指令,这次TLB会命中。

但是如果希望允许页交换到磁盘,必须添加更多的机制。具体来说就是,硬件在页表项中查找时,可能发现页不在物理内存中。硬件判断是否在内存中的方法,是通过页表项的一个标识,即存在位。如果存在位设置为1,则表示该页存在于物理内存中。如果设置为0,则页不在内存中,而在硬盘上。访问不在内存中的页,这种行为被称为页错误(page fault)。

如果页不存在时,都是由操作系统来处理页错误。操作系统需要知道所需要的页在哪里,一般都是把信息存放在页表中,利用页表项的一些位来存储磁盘地址。当操作系统接收到页错误时,他会在页表项中查找地址,并将请求发送到磁盘,将页读到内存中。当磁盘IO完成时,操作系统会更新页表,标记为该页存在,并更新页表项中的物理帧号来记录页的内存位置,并重试指令。下一次重新访问TLB还是未命中,再走一遍上述过程,将页表中的地址更新到TLB中。

在磁盘IO时,进程将处于阻塞状态,因此发生页错误时,操作系统会运行其他可执行的程序,即发生进程调度。

页错误的时,操作系统的一个大概处理流程,首先,操作系统必须要为将要换入的页找到一个物理帧,如果没有这样的物理帧,将不得不等待交换算法的运行,从内存中剔除一些页,释放振供着里使用。在获得物理帧后,处理程序发出IO请求从交换空间读取页。最后,当这个IO操作完成时,操作系统更新页表并重试指令。重试将导致TLB未命中,然后再一次重试,TLB命中,此时硬件将可以正常访问所需的值。

交换是在什么时候发生的?首先肯定不能等到内存满了再发生交换,所以操作系统会更主动的预留一小部分空闲内存。大多数的操作系统都会设置高水位线、低水位线。当操作系统发现有少于低水位个页可用时,后台释放内存的线程会开始运行,直到有高水位个可用页。这个后台线程被称为交换守护进程或者页守护进程,然后它会进入休眠状态。

这个过程一般会有一些性能优化,许多系统会把要写入的页2或分组,同时写入到交换空间,提高磁盘效率。

把工作放到后台,是个比较常见的优化手段,通常把操作放在后台,一方面可以允许这些操作合并执行,一方面更好的利用了空闲时间。

再一次印证了我的那句话,所有好的设计、实践,几乎都来自于操作系统,或者说操作系统都已经实践过了。

公众号:

操作系统导论-内存篇3

上一篇:TLB


下一篇:计算机操作系统、计算机原理 - 地址翻译