【操作系统】八、虚拟内存

明确概念

虚拟内存:在存储分配机制中,尽管备用内存是主内存的一部分,它也可以被寻址。程序引用内存使用的地址与内存系统用于识别物理存储站点的地址是不同的,程序生成的地址会自动转换成机器地址。虚拟存储的大小受到计算机系统寻址机制和可用的备用内存量的限制,而不受内存储位置实际数量的限制。

虚拟地址:在虚拟内存中分配给某一位置的地址使该位置可以被访问,彷佛它是主内存的一部分。

虚拟地址空间:分配给进程的虚拟存储

地址空间:可用于某进程的内存地址范围

实地址:内存中存储位置的地址

8.1硬件和控制结构

我们已知分页和分段有两个特点:

1.进程中的所有内存访问都是逻辑地址,这些逻辑地址在运行时动态地被转换成物理地址。这意味着一个进程可以被换入或换出内存,使得进程可以在执行过程中的不同时刻占据内存的不同区域。

2.一个进程可以划分成许多块(页和段),在执行过程中,这些块不需要连续地位于内存中。动态运行时地址转换和页表或段表的使用使这一点成为可能。

这就使得在进程的执行过程中,该进程不需要所有页或所有段都在内存中。如果内存中保存着要取的下一条指令的所在块(段或页),以及将要访问的下一个数据单元的所在块,那么进程的执行至少可以暂时继续下去。

过程如下:假设需要把一个新进程放入内存时,操作系统仅读取包含程序开始处的一个或几个块。进程执行中的任何时候都在内存的部分称为进程的常驻集。当进程执行时,只要所有的内存访问都是要访问常驻集中的单元,执行就可以顺利进行;使用段表或页表,处理器总是可以确定是否如此。如果处理器需要访问一个不在内存中的逻辑地址,则产生一个中断,说明产生了内存访问故障。操作系统把被中断的进程置于阻塞态。为了能继续执行这个进程,操作系统必须把包含引发访问故障的逻辑的地址的进程块读入内存。为此,操作系统产生一个磁盘I/O读请求。产生I/O读请求后,在执行磁盘I/O期间,操作系统可以调度另一个进程运行。一旦需要的块被读入内存,则产生一个I/O中断,控制权交回给操作系统,而操作系统把由于缺少该块而被阻塞的进程置为就绪态。

由于一个进程只能在内存中执行,因此这个存储器称为实存储器,但是用户会感到一个更大的内存,通常它被分配在磁盘上,这称为虚拟内存,虚存支持更有效地多道程序设计,并解除了用户与内存之间没有必要的紧密约束。

8.1.1局部性和虚拟内存

 考虑以下情况:一个由很长的程序和许多个数组的数据组成的大进程,在任何一段很短的时间内,执行可能会局限在很小的一段程序中(如一个子程序),并且可能仅仅会访问一个或两个数组的数据。这样,如果程序被挂起或被换出前仅仅使用了这一部分进程块,那么装入太多的块就会带来巨大的浪费。可以通过仅仅装入这一小部分块来更好地使用内存。然后在需要其它块时,引发一个错误从而去读取。

因此在任何时刻,内存中有着许多个进程的部分块,从而提高了CPU的使用率。

如果一块正好在将要被用到之前换出,操作系统就不得不很快把它取回来。太多的这类操作会导致一种称为系统抖动的情况:处理器的大部分时间都用于交换块,而不是执行指令。

从本质上看,这些算法都是操作系统试图根据最近的历史来猜测在不远的将来最可能用到的块。这类推断基于局部性原理

8.1.2分页

基于分页的虚拟内存方案与简单分页方案类似,也同样需要页表,并且通常每个进程都有一个唯一的页表,但这时页表项变得复杂。

 如图所示,增加了P和M等控制位,其中P表示该页是否在内存中,M表示该页的内容是否被改变,如果未改变,则当需要把该页换出时,不需要用页框中的内容更新该页。

页表结构

从内存中读取一个字的基本机制包括使用页表从虚拟地址到物理地址的转换。虚拟地址又称为逻辑地址,由页号偏移量组成,而物理地址由页框号偏移量组成。页表也被保存在内存中。

 但是若每个进程的虚存空间太大,则每个进程需要很多的页表项。显然,这样子的话来放置页表的内存空间就太大了。为了克服这个问题,大部分的虚拟内存方案都在虚存而非实存中保存页表。这意味着页表和其他页一样都服从分页管理。

 假设采用字节级的寻址,页尺寸为4KB,则4GB的虚拟地址空间由2^20页组成。若这些页中的每页都由一个4B的页表项映射,则可创建由2^20个页表项组成的一个页表,这时需要4MB的内存空间。这个由2^10页组成的巨大用户页表可以保存在虚存中,并由一个包括2^10个页表项的根页表映射,根页表占据的内存为4KB。

倒排页表 前述页表设计的一个重要缺陷是,页表的大小与虚拟地址空间的大小成正比。

在这个方法中,虚拟地址的页号部分使用一个简单的散列函数映射到散列表中。散列表包含指向倒排表的指针,而倒排表中含有页表项。采用这种结构后,散列表和倒排表中就各有一项对应于一个实存页而非虚存页。因此,不论有多少进程、支持多少虚拟页,页表都只需要实存中的一个固定部分。由于多个虚拟地址可能映射到同一个散列表项中,因此需要使用一种链接技术来管理这种一处。散列技术可使链较短,通常只有一到两项。页表结构称为倒排的原因是,它使用页框号而非虚拟页号来索引页表项。

转换检测缓冲区 原则上,每次虚存访问都可能会引起两次物理内存访问:一次取相应的页表项,另一次取需要的数据。因此,简单的虚拟内存方案会导致访问时间加倍。为克服这个问题,大多数虚拟内存方案都为页表项使用了一个特殊的高速缓存,通常称为转换检测缓冲区(Translation Lookaside Buffer,TLB)。这个高速缓存的功能和高速缓冲存储器(Cache)相似,包含有最近用过的页表项。

因此得到如下过程:给定一个虚拟地址,处理器首先检查TLB,若需要的页表项在其中(TLB命中),则检索页框号并形成实地址。若未找到需要的页表项(TLB未命中),则处理器用页号检索页表,并检查相应的页表项了。若”存在位”已置为,则改也在内存中,处理器从页表项中检索页框号以形成实地址。处理器同时更新TLB,使其包含这个新页表项。最后。若“存在位“未置位,则表示需要的页不在内存中,这时会产生一次内存访问故障,称为缺页(page fault)中断。此时离开硬件作用范围,调用操作系统,由操作系统负责装入所需要的页,并更新页表。 

 

页尺寸 页尺寸是一个重要的硬件设计决策,它需要考虑多方面的因素。一个是内部碎片,页越小,内部碎片就越少,另一方面,页越小,页表就越大。另一个因素是基于大多数辅存设备的物理特性,希望页尺寸比较大,从而实现更有效地数据块传送。

一般而言,基于局部性原理,其性能如图所示。

 8.1.3分段

虚拟内存分段方案与简单分段类似,分段允许程序员把内存视为由多个地址空间或段组成,段的大小不等,并且是动态的。内存访问以段号和偏移量的形式组成地址。

优点:

1.简化了对不断增长的数据结构的处理。

2.允许程序独立地改变或重新编译。

3.有助于进程间的共享。

4.有助于保护。

在虚拟内存分段方案中,也需要段表这个设计。与页表类似,段表也需要增加修改位,与是否在内存位等控制位。

地址转换过程如下:

 8.1.4段页式

分段分页各有长处。

在段页式系统中,用户的地址空间被程序员划分为许多段。每段依次划分为许多固定大小的页,页的长度等于内存中页框大小。若某段的长度小于一页,则该段只占据一页。从程序员的角度看,逻辑地址仍然由段号和段偏移量组成;从系统的角度看,段偏移量可视为枝顶端中的一个页号和页偏移量。

段页式系统中的地址转换如下:

 8.2操作系统软件

操作系统的内存管理设计取决于三个基本的选择:

1.是否使用虚存

2.是使用分页还是使用分段,或同时使用二者

3.为各种存储管理特征采用的算法

本节主要讨论第三个问题。

8.2.1读取策略

读取策略决定某页何时取入内存,常用的两种方法是请求分页(demand paging)预先分页(prepaging)。对于请求分页,只有当访问到某页中的一个单元时才将该页取入内存。因此在一个进程首次启动时,采取请求分页会导致在一段时间内出现大量的缺页中断。

预先分页利用了大多数辅存设备(如磁盘)的特性,这些设备有寻道时间和合理的延迟。若一个进程的页连续存储在辅存中,则一次读取许多连续的页要比隔一段时间读取一页有效。

8.2.2放置策略

放置策略决定一个进程块驻留在实存中的什么位置。在纯分段系统中,放置策略并不是重要的设计问题,第七章中的最佳适配、首次适配等都可供选择。但对于纯分页系统或段页式系统,如何放置通常无关紧要,因为地址转换硬件和内存访问硬件能以相同的效率为任何页框执行相应的功能。

8.2.3置换策略

8.2.3.1最佳置换算法(OPT)

最佳置换算法:每次淘汰的页面将是以后用不使用,或者在最长时间内不再被访问的页面,这也可以保证最低的缺页率。

概念很好理解,直接上题:

 最佳置换算法可以保证最低的缺页率,但是只有知道进程执行的过程,但是操作系统无法提前预判页面访问序列,因此,最佳置换算法是无法实现的。

8.2.3.2先进先出置换算法(FIFO)

先进先出置换算法:每次选择淘汰的页面是最早进入内存的页面

实现方法:把调入内存的页面根据调入的先后顺序排成一个队列,需要换出页面时选择对头页面即可。队列的最大长度取决于系统为进程分配了多少个内存块。

Beledy异常:当为进程分配的物理块数增大时,缺页次数不减反增的异常现象。

8.2.3.3最近最久未使用置换算法(LRU)

最近最久未使用置换算法:每次淘汰的页面是最近最久未使用的页面

实现方法:赋予每个页面对应的页表项,用访问字段记录该页面自上次被访问以来所经理的时间t。

当需要淘汰一个页面时,选择现有页面中t值最大的,即最近最久未使用的页面。

 缺点:开销太大

8.2.3.4时钟置换算法(CLOCK)

简单的CLOCK算法

简单的CLOCK算法实现方法为:为每个页面设置一个访问位, 再将内存中的页面都通过链接指针链接成一个循环队列。当某一页首次装入内存时,则将该页框的使用位置为1;当该页随后被访问到时(在访问产生缺页中断之后),它的使用位也会被置为1。对于页面置换算法,用于置换的候选页框集合(当前进程:局部范围;整个内存:全局范围)被视为一个循环缓冲区,并且有一个指针与之相关联。当一页被置换时,该指针被设置成指向缓冲区中的下一页框。当需要置换一页时,操作系统扫描缓冲区,以查找使用位被置为0的一个页框。每当遇到一个使用位为1的页框,将该位置为0;如果在这个过程开始时,缓冲区中的所有页框的使用位均为0,则选择遇到的第一个页框置换;如果所有页框的使用位均为1,则指针在缓冲区中的完整的循环一周,把所有使用位都置为0,并且停留在最初的也位置上,置换该页框中的页。

 

 简单的时钟置换算法仅考虑到一个页面最近是否被访问过。事实上,如果被淘汰的页面没有被修改过,就不需要执行I/O操作写回外存。只有被淘汰的页面被修改过时,才需要写回外存。

改进型的时钟置换算法

改进型的时钟置换算法增加了使用的位数。在所有支持分页的处理器中,内存中的每页都有一个与之关联的修改位,因此内存中的每个页框也与这些修改位相关联。修改位是必需的,若某页被修改,则它在被写回外村前不会被置换出。若一起考虑使用位和修改位,则有如下四种情况:

 则该时钟算法的执行过程如下:

8.2.4驻留集管理

 驻留集在前面提到过,也就是任何时刻在内存中的个部分称为进程的驻留集。

则如何给进程在内存中分配页框就是一个问题

基于如下两种策略:

固定分配策略:每次分配固定数量的页框

可变分配策略:允许分配给一个进程的页框在该进程的生命周期中不断地发生变化

如何置换页框也是一个问题

有如下两种策略:

局部置换策略:仅在产生这次缺页的进程的驻留页中选择

全局置换策略:把内存中所有未被锁定的页都作为置换的候选页

 8.2.5清除策略

与读取式策略相反,清除策略用于确定何时将修改的页写回辅存

有两种选择:

请求式清除:只有当一页被选择用于置换时才被写回辅存

预约式清除:将这些已修改的多页在需要使用它们所占据的页框之前成批写回辅存

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

噶炜123

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值