存储器管理
1.多层结构的存储器系统
存储器的多层结构。
存储层次至少应具有三级:最高层为 CPU 寄存器,中间为主存,最底层是辅存。还可以根据具体的功能分工细划为寄存器、高速缓存、主存储器、磁盘缓存、固定磁盘、可移动存储介质等 6 层。在存储层次中越往上,存储介质的访问速度越快,价格也越高,相对存储容量也越小。
![](https://i-blog.csdnimg.cn/blog_migrate/10ffe27e4d19314a80755293315652bd.png)
主存储器与寄存器
- 主存储器。
- 主存储器简称内存或主存。由于主存储器的访问速度远低于 CPU 执行指令的速度,为缓和这一矛盾,在计算机系统中引入了寄存器和高速缓存。
- 寄存器。
- 寄存器具有与处理机相同的速度。主要用于存放处理机运行时的数据。如用寄存器存放操作数,或用作地址寄存器加快地址转换速度等。
高速缓存和磁盘缓存
- 高速缓存。
- 高速缓存是介于寄存器和存储器之间的存储器,主要用于备份主存中较常用的数据。其容量远大于寄存器,而比内存约小两到三个数量级左右。根据程序执行的局部性原理(即程序在执行时将呈现出局部性规律,在一较短的时间内,程序的执行仅局限于某个部分),将主存中一些经常访问的信息存放在高速缓存中。当 CPU 访问一组特定信息时,首先检查它是否在高速缓存中,在则直接取出使用,否则再从主存中读取。
- 磁盘缓存。
- 由于目前磁盘的 I/O 速度远低于对主存的访问速度,因此将频繁使用的一部分磁盘数据和信息,暂时存放在磁盘缓存中,可减少访问磁盘的次数。但磁盘缓存与高速缓存不同,它本身并不是一种实际存在的存储介质,而是利用主存中的部分存储空间暂存从磁盘中读出(或写入)的信息。
2.程序的装入和链接
用户程序要在系统中运行,必须先将它装入内存,然后再将其转变为一个可以执行的程序,通常都要经过以下几个步骤:
- 编译,由编译程序将用户源代码编译成若干个目标模块。
- 链接,由链接程序将编译后形成的一组目标模块,以及它们所需要的库函数链接在一起,形成一个完整的装入模块。
- 装入,由装入程序将装入模块装入内存。
连续分配存储管理方式
为了能将用户程序装入内存,必须为它分配一定大小的内存空间。
单一连续分配
- 只能用于单道程序环境下,整个内存的用户空间由一个程序独占。
固定分区分配
- 将内存用户空间划分为若干个固定大小的区域,在每个分区中只装入一道作业。
- 划分分区的方法:分区大小相等、分区大小不等。
- 内存分配:通常将分区按大小进行排队,并为之建立一张分区使用表,其中各表项包括每个分区的起始地址、大小及状态(是否已分配)。当有一用户程序要装入时,由内存分配程序检索该表,从中找出一个能满足要求的、尚未分配的分区,将之分配给该程序,然后将该表项中的状态置为“已分配”。
动态分区分配
又称可变分区分配。
- 动态分区分配中的数据结构。
- 常用的数据结构有以下两种形式:
- 空闲分区表,表目:分区号、分区大小、分区始址、状态。
- 空闲分区链,在每个分区的起始部分设置一些用于控制分区分配的信息,以及用于链接各分区所用的前向指针;在分区尾部则设置一后向指针,以及前后都重复设置状态位和分区大小表目。通过前、后向链接指针,可将所有的空闲分区链接成一个双向链。
- 常用的数据结构有以下两种形式:
- 动态分区分配算法。
- 顺序式搜索算法、索引式搜索算法。
- 分区分配操作。
- 分配内存:
- 系统应利用某种分配算法,从空闲分区链(表)中找到所需大小的分区。设请求的分区大小为 u.size,表中每个空闲分区的大小可表示为 m.size。若 m.size-u.size≤size(size 是事先规定的不再切割的剩余分区的大小),说明多余部分太小,可不再切割,将整个分区分配给请求者;否则(即多余部分超过 size),从该分区中按请求的大小划分出一块内存空间分配出去,余下的部分仍留在空闲分区链(表)中。然后,将分配区的首址返回给调用者。
- 回收内存:
- 当进程运行完毕释放内存时,系统根据回收区的首址,从空闲区链(表)中找到相应的插入点,此时可能出现以下四种情况之一:
- 回收区与插入点的前一个空闲分区相邻接,此时应将回收区与插入点的前一分区合并。
- 回收分区与插入点的后一空闲分区相邻接,此时也可将两分区合并。
- 回收区同时与插入点的前、后两个分区邻接,此时将三个分区合并。
- 回收区既不与前一个邻接,又不与后一个邻接,这时应为回收区单独建立一新表项,填写回收区的首址和大小,并根据其首址插入到空闲链中的适当位置。
- 当进程运行完毕释放内存时,系统根据回收区的首址,从空闲区链(表)中找到相应的插入点,此时可能出现以下四种情况之一:
- 分配内存:
基于顺序搜索的动态分区分配算法
顺序搜索,是指依次搜索空闲分区链上的空闲分区,去寻找一个其大小能满足要求的分区。
碎片:内存空间不断被划分,会留下许多难以利用的、很小的空闲分区。
- 首次适应算法
- 要求空闲分区链以地址递增的次序链接。在分配内存时,从链首开始顺序查找,直至找到一个大小能满足要求的空闲分区为止,缺点是低址部分会不断被划分,形成碎片。
- 循环首次适应算法
- 在为进程分配内存空间时,不再是每次都从链首开始查找,而是从上次找到的空闲分区的下一个空闲分区开始查找。实现可通过设置一起始查寻指针,用于指示下一次起始查寻的空闲分区,并采用循环查找方式。缺点缺乏大的空闲分区。
- 最佳适应算法
- 总是把能满足要求、又是最小的空闲分区分配给作业,为了加速寻找,该算法要求将所有的空闲分区按其容量以从小到大的顺序形成一空闲分区链。缺点产生许多碎片。
- 最坏适应算法
- 在扫描整个空闲分区表或链表时,总是挑选一个最大的空闲区,分割一部分空间给作业使用。要求将所有的空闲分区按其容量以从大到小的顺序形成一空闲分区链,查找时只要看第一个分区能否满足作业要求即可。缺点缺乏大的空闲分区。
基于索引搜索的动态分区分配算法
- 快速适应算法
- 又称为分类搜索法。是将空闲分区根据其容量大小进行分类,对于每一类具有相同容量的所有空闲分区,单独设立一个空闲分区链表,同时在内存中设立一张管理索引表,该表的每一个表项对应了一种空闲分区类型,并记录了该类型空闲分区链表表头的指针。
- 该算法仅需要根据进程的长度,寻找到能容纳它的最小空闲区链表,并取下第一块进行分配即可。在分配过程中,不会对任何分区产生分割。
- 伙伴系统
- 伙伴系统是连续存储分配的一种办法。它比较好地折中了分配和回收过程中分配块的位置碎片和合并的问题。伙伴系统地概念如下图:整个可分配分区大小为2的幂次方,当需要的内存空间大于当前块的一半的时候就将整个分区分配给进程,如果小于当前分区的一半,就将当前分区对半分开,将其中一半继续与需要的内存大小进行比较,递归进行下去,直到满足所需内存大小大于分区一半。可以看到这种分配方式内部碎片最大为分区大小的一半减一。
- 哈希算法
- 构造一张以空闲分区大小为关键字的哈希表,该表的每一个表项记录了一个对应的空闲分区链表表头指针。
3.分页存储管理方式
分页存储管理的基本方法
- 页面和物理块。
- 页面:将一个进程的逻辑地址空间分成若干个大小相等的片,称为页面或页,并为各页加以编号。相应地,也把内存的物理空间分成若干个块,并为各块加以编号。在为进程分配内存时,以块为单位将进程中的若干个页分别装入到多个可以不相邻接的物理块中。由于进程的最后一页经常装不满一块而形成了不可利用的碎片,称之为“页内碎片”。
- 页面大小:页面的大小应选择适中,且页面大小应是 2 的幂,通常为 1 KB~8 KB。
- 地址结构。
其中,INT 是整除函数,MOD 是取余函数。例如,其系统的页面大小为 1 KB,设 A = 2170 B,则由上式可以求得 P = 2,d = 122。
- 逻辑地址的地址结构如下:
- 含有两部分:前一部分为页号 P,后一部分为位移量 W(或称为页内地址)。图中的地址长度为 32 位,其中 0~11 位为页内地址,即每页的大小为 4 KB;12~31 位为页号,即地址空间最多允许有 1 M 页。可见系统中允许的最大进程为4kb * 2^20 = 4GB。
- 对于某特定机器,其地址结构是一定的。若给定一个逻辑地址空间中的地址为 A,页面的大小为 L,则页号 P 和页内地址 d 可按下式求得:
-
页号=逻辑地址/页面长度(整除)
-
页内偏移量=逻辑地址%页面长度(取余)
- 逻辑地址的地址结构如下:
- 例题
- 有一系统采用页式存储管理,有一作业大小是8KB,页大小为2KB,依次装入内存的第7,9,10,5块,试将虚地址7165,3412转换成内存地址
-
页号 块号 0 7 1 9 2 10 3 5 -
虚地址3412: P=3412 % 2048 = 1 //得到页号为1
-
W=3412 mod 2048 = 1364 //页内偏移量为1364
-
MA = 9 * 2048 + 1364 = 19796 //为什么是9*2048?因为页号1所对应的内存块号是9
-
则虚地址3412对应的内存地址为19796
- 页表
- 为保证进程的正确运行,即能在内存中找到每个页面所对应的物理块。为此,系统又为每个进程建立了一张页面映像表,简称页表。在进程地址空间内的所有页,依次在页表中有一页表项,其中记录了相应页在内存中对应的物理块号。可见,页表的作用是实现从页号到物理块号的地址映射。
地址变换机构
实现从逻辑地址到物理地址的转换。由于页内地址和物理地址是一一对应的(例如,对于页面大小是 1 KB 的页内地址是 0~1023,其相应的物理块内的地址也是 0~1023,无须再进行转换),因此,地址变换机构的任务实际上只是将逻辑地址中的页号,转换为内存中的物理块号。又因为页面映射表的作用就是用于实现从页号到物理块号的变换,因此,地址变换任务是借助于页表来完成的。
- 基本的地址变换机构。
- 页表大多驻留在内存中。在系统中只设置一个页表寄存器 PTR,在其中存放页表在内存的始址和页表的长度。平时,进程未执行时,页表的始址和页表长度存放在本进程的 PCB 中。当调度程序调度到某进程时,才将这两个数据装入页表寄存器中。因此,在单处理机环境下,虽然系统中可以运行多个进程,但只需一个页表寄存器。
- 当进程要访问某个逻辑地址中的数据时,分页地址变换机构会自动地将有效地址(相对地址)分为页号和页内地址两部分,再以页号为索引去检索页表。查找操作由硬件执行。
- 在执行检索之前,先将页号与页表长度进行比较,如果页号大于或等于页表长度,则表示本次所访问的地址已超越进程的地址空间。于是,这一错误将被系统发现并产生一地址越界中断。
- 若未出现越界错误,则将页表始址与页号和页表项长度的乘积相加,便得到该表项在页表中的位置,于是可从中得到该页的物理块号,将之装入物理地址寄存器中。
- 与此同时,再将有效地址寄存器中的页内地址送入物理地址寄存器的块内地址字段中。这样便完成了从逻辑地址到物理地址的变换。
- 具有快表的地址变换机构
- 由于页表是存放在内存中的,这使CPU在每存取一个数据时,都要两次访问内存。第一次是访问内存中的页表,从中找到指定页的物理块号,再将块号与页内偏移量W拼接,以形成物理地址。第二次访问内存时,才是从第一次所得地址中获得所需数据。
- 为了提高地址变换速度,可在地址变换机构中增设一个具有并行查寻能力的特殊高速缓冲寄存器,又称为“联想寄存器”,或称为“快表”,在 IBM 系统中又取名为 TLB,用以存放当前访问的那些页表项。此时的地址变换过程是:
- 在 CPU 给出有效地址后,由地址变换机构自动地将页号 P 送入高速缓冲寄存器,并将此页号与高速缓存中的所有页号进行比较,若其中有与此相匹配的页号,便表示所要访问的页表项在快表中。于是,可直接从快表中读出该页所对应的物理块号,并送到物理地址寄存器中。
- 如在块表中未找到对应的页表项,则还须再访问内存中的页表,找到后,把从页表项中读出的物理块号送地址寄存器;同时,再将此页表项存入快表的一个寄存器单元中,亦即,重新修改快表。但如果联想寄存器已满,则 OS 必须找到一个老的且已被认为不再需要的页表项,将它换出。
计算访问一个物理单元的时间
-
这里牵涉到快表(TLB)的访问时间,页表的访问时间,虚拟地址和物理地址的转换,内存访问时间的概念
-
例题:
-
假设快表命中率是98%,访问时间是10ns,内存访问时间是100ns,求平均访问时间?
-
平均访问时间=98%(10+100)+(1-98%)(10+100+100)
-
-
解析:
-
若快表命中
-
TLB检索时间:10ns;
-
访问内存一次取得数据时间:100ns;
-
总时间:110ns
- 若快表未命中
- TLB检索时间:10ns;
- 访问内存一次检索页表时间:100;
- 访问内存一次取得数据时间:100ns;
- 总时间:210ns
-
两级和多级页表
现代的大多数计算机系统,都支持非常大的逻辑地址空间,因此页表就变得非常大,要占用相当大的内存空间。因为每个页表项占用一个字节,故页表长度 * 1字节就是页表所占的内存空间大小。且页表内存空间还要求是连续的,显然这是不现实的。
解决方法:
- 对于页表所需的内存空间,可采用离散分配方式来解决难以找到一块连续的大内存空间的问题;
- 只将当前需要的部分页表项调入内存,其余的页表项仍驻留在磁盘上,需要时再调入。
两级页表:
- 将页表进行分页,然后离散地将各个页面分别存放在不同的物理块中。也要为离散分配的页表再建立一张页表,称为外层页表,在每个页表项中记录了页表页面的物理块号。
- 以前面的 32 位逻辑地址空间为例来说明,当页面大小为 4 KB 时,采用两级页表结构时,再对页表进行分页,使每页中包含 2^10 (即 1024)个页表项,最多允许有 2^10个页表分页。此时的逻辑地址结构如下:
- 在页表的每个表项中存放的是进程的某页在内存中的物理块号,而在外层页表的每个页表项中,所存放的是某页表分页的在内存中的物理块号。可以利用外层页表和页表这两级页表,来实现从进程的逻辑地址到内存中物理地址间的变换。在地址变换机构中同样需要增设一个外层页表寄存器,用于存放外层页表的始址,并利用逻辑地址中的外层页号,找到指定页表分页的始址,再根据外层页内地址找到指定的页表项,再从该页表项中读出该页在内存中的物理块号。
- 虽然解决了对大页表无需大片连续存储空间的问题,但并未解决用较少的内存空间去存放大页表的问题。只用离散分配空间的办法并未减少页表所占用的内存空间。解决方法是把当前需要的一批页表项调入内存,以后再根据需要陆续调入。在采用两级页表结构的情况下,对于正在运行的进程,必须将其外层页表调入内存,而对页表则只需调入一页或几页。为了表征某页的页表是否已经调入内存,还应在外层页表项中增设一个状态位 S,其值若为 0,表示该页表分页尚未调入内存;否则,
- 说明其分页已在内存中。进程运行时,地址变换机构根据逻辑地址中的外层页号 P1,去查找外层页表;若所找到的页表项中的状态位为 0,则产生一中断信号,请求 OS 将该页表分页调入内存。
多级页表:
- 对于 32 位的机器,采用两级页表结构是合适的;但对于 64 位的机器,必须采用多级页表,将外层页表再进行分页。
4.分段存储管理方式
分段存储管理方式的引入
- 方便编程
- 通常,用户把自己的作业按照逻辑关系划分为若干个段。程序员们都迫切地需要访问的逻辑地址是由段名(段号)和段内偏移量(段内地址)决定的。
- 信息共享
- 实现对程序和数据的共享时,是以信息的逻辑单位为基础的。分页系统中的“页”只是存放信息的物理单位(块),并无完整的意义。而段却是信息的逻辑单位,因此可以为该被共享过程建立一个独立的段,极大地简化了共享的实现。
- 信息保护
- 信息保护同样是对信息的逻辑单位进行保护的。在分页系统中,一个函数可能要占用若干个页面,而且其中的第一个和最后一个页面还会装有其它程序段的数据,它们可能有着不同的保护属性。
- 动态增长
- 在实际使用中,往往有些段特别是数据段,会不断地增长,而事先又无法确切地知道数据段会增长到多大。这种动态增长地情况是其它几种存储管理方式都难于应付的;而分段存储管理方式却能较好地解决这一问题。
- 动态链接
- 运行时动态链接要求的是以目标程序(即段)作为链接的基本单位,因此,分段存储管理方式非常适合动态链接。
分段系统的基本原理
- 分段
- 作业的地址空间被划分为若干个段,每个段定义了一组逻辑信息。每个段都从 0 开始编址,并采用一段连续的地址空间。段的长度由相应的逻辑信息组的长度决定,因而各段长度不等。整个作业的地址空间由于是分成多个段,因而呈现出二维特性。其逻辑地址由短号和段内地址组成。
- 段表
- 在分段式存储管理系统中,则是为每个分段分配一个连续的分区,而进程中的各个段可以离散地移入内存中不同的分区中。在系统中为每个进程建立一张段映射表,简称“段表”。每个段在表中占有一个表项,其中记录了该段在内存中的起始地址(又称为“基址”)和段的长度。可见,段表是用于实现从逻辑段到物理内存区的映射。
- 地址变换机构
- 为了实现从进程的逻辑地址到物理地址的变换功能,在系统中设置了段表寄存器,用于存放段表始址和段表长度 TL。在进行地址变换时,系统将逻辑地址中的段号与段表长度TL 进行比较。若 S>TL,表示段号太大,是访问越界,于是产生越界中断信号;若未越界,则根据段表的始址和该段的段号,计算出该段对应段表项的位置,从中读出该段在内存的起始地址,然后,再检查段内地址 d 是否超过该段的段长 SL。若超过,即 d>SL,同样发出越界中断信号;若未越界,则将该段的基址与段内地址相加,即可得到要访问的内存物理地址。
- 像分页系统一样,当段表放在内存中时,每要访问一个数据,都须访问两次内存,从而极大地降低了计算机的速率。解决的方法也和分页系统类似,再增设一个联想存储器,用于保存最近常用的段表项。
- 分页和分段的主要区别
- 相似之处:
- 两者都采用离散分配方式,且都要通过地址映射机构来实现地址变换。
- 不同:
- 页是信息的物理单位,分页是为了提高内存的利用率。段则是信息的逻辑单位,分段的目的是为了能更好地满足用户的需要。
- 页的大小固定且由系统决定。而段的长度却不固定,决定于用户所编写的程序。
- 分页中用户程序的的逻辑地址空间是一维的,分页完全是系统的行为,只需要一个记忆符即可表示一个地址。而分段中用户程序的逻辑地址空间是二维的,在标识一个地址时,既需给出段名, 又需给出段内地址(正是因为段的大小不固定导致的)。
- 相似之处:
-
信息共享
-
分页系统中对程序和数据的共享
-
虽然也能实现对程序和数据的共享,但远不如分段系统来得方便
-
-
-
-
分段系统中对程序和数据的共享
-
可重入代码又称为“纯代码”,是一种允许多个进程同时访问的代码。可重入代码是一种不允许任何进程对它进行修改的代码。但事实上,大多数代码在执行时都可能有些改变。为此,在每个进程中,都必须配以局部数据区,把在执行中可能改变的部分拷贝到该数据区,这样,程序在执行时,只需对该数据区(属于该进程私有)中的内容进行修改,并不去改变共享的代码,这时的可共享代码即成为可重入码。
-
-
段页式存储管理方式
- 基本原理
- 段页式系统的基本原理是分段和分页原理的结合,即先将用户程序分成若干个段,再把每个段分成若干个页,并为每一个段赋予一个段名。在段页式系统中,其地址结构由段号、段内页号及页内地址三部分所组成。
- 为了实现从逻辑地址到物理地址的变换,系统中需要同时配置段表和页表。段表的内容与分段系统略有不同,它不再是内存始址和段长,而是页表始址和页表长度。即一个分段对应一个页表。
- 地址变换过程
- 为了便于实现地址变换,须配置一个段表寄存器,其中存放段表始址和段长TL。进行地址变换时,首先利用段号S,将它与段长TL进行比较。若S < TL,表示未越界,于是利用段表始址和段号来求出该段所对应的段表项在段表中的位置,从中得到该段的页表始址,并利用逻辑地址中的段内页号P来获得对应页的页表项位置,从中读出该页所在的物理块号b,再利用块号b和页内地址来构成物理地址。
- 在段页式系统中,为了获得一条指令或数据,须三次访问内存。第一次访问是访问内存中的段表,从中取得页表始址;第二次访问是访问内存中的页表,从中取出该页所在的物理块号,并将该块号与页内地址一起形成指令或数据的物理地址;第三次访问才是真正从第二次访问所得的地址中,取出指令或数据。
- 解决方法仍类似快表。在地址变换机构中增设一个高速缓冲寄存器。每次访问它时,都须同时利用段号和页号去检索高速缓存,若找到匹配的表项,便可从中得到相应页的物理块号,用来与页内地址一起形成物理地址;若未找到匹配表项,则仍须再三次访问内存。
5. 虚拟存储器
- 虚拟存储器的定义
- 所谓虚拟存储器,是指具有请求调入功能和置换功能,能从逻辑上对内存容量加以扩充的一种存储器系统。其逻辑容量由内存容量和外存容量之和所决定,其运行速度接近于内存速度,而每位的成本却又接近于外存。
- 虚拟存储器的特征
- 多次性
- 是指一个作业中的程序和数据无需在作业运行时一次性地全部装入内存,而是允许被分成多次调入内存运行,即只需将当前要运行的那部分程序和数据装入内存即可开始运行。
- 对换性
- 是指一个作业中的程序和数据,无须在运行时一直常驻内存,而是允许在作业的运行过程中进行换进、换出。
- 虚拟性
- 是指能够从逻辑上扩充内存容量,使用户所看到的内存容量远大于实际内存容量。就可以在小的内存中运行大的作业,或者能提高多道程序度。虚拟性是以多次性和对换性为基础的,而多次性和对换性是必须建立在离散分配的基础上。
- 多次性
- 虚拟存储器的实现方法
- 分页请求系统
- 这是在分页系统的基础上,增加了请求调页功能和页面置换功能所形成的页式虚拟存储系统。置换时以页面为单位。
- 硬件支持
- 请求分页的页表机制。
- 缺页中断机构。
- 地址变换机构。
- 实现请求分页的软件
- 包括有用于实现请求调页的软件和实现页面置换的软件。
- 分段请求系统
- 这是在分段系统的基础上,增加了请求调段及分段置换功能后所形成的段式虚拟存储系统。置换时以段为单位。
- 硬件支持。
- ①请求分段的段表机制。
- ②缺段中断机构。
- ③地址变换机构。
- 实现请求分段的软件。
- 包括有用于实现请求调段的软件和实现段置换的软件。
- 因为请求分页系统换进和换出的基本单位都是固定大小的页面,所以在实现上要容易些。而请求分段系统换进换出的基本单位是段,其长度是可变的,分段的分配类似于动态分区方式,它在内存分配和回收上都比较复杂。
- 段页式虚拟存储器系统
- 在段页式系统基础上,增加请求调页和页面置换功能形成段页式虚拟存储器系统。
- 分页请求系统
6.请求分页存储管理方式
请求分页中的硬件支持
- 请求页表机制
- 在请求页表中增加了四个字段:
- 状态位(存在位) P:指示该页是否已调入内存。
- 访问字段A:记录该页在一段时间内的访问次数,或者最近多久未被访问,为置换算法选择置换页提供参考;
- 修改位M:指示该页在调入内存后是否被修改过。
- 外存地址:指示该页在外存的地址,通常是物理块号。
- 缺页中断机构
- 在请求分页系统中,每当所要访问的页面不在内存时,便产生一缺页中断,请求 OS 将所缺之页调入内存。缺页中断作为中断,它们同样需要经历诸如保护 CPU 环境、分析中断原因、转入缺页中断处理程序进行处理、恢复 CPU 环境等几个步骤。但缺页中断又是一种特殊的中断,它与一般的中断相比,有着明显的区别,主要表现在下面两个方面:
- 在指令执行期间产生和处理中断信号。即在指令执行期间,发现所要访问的指令或数据不在内存时所产生和处理的。
- 一条指令在执行期间,可能产生多次缺页中断。并保证最后能返回到中断前产生缺页中断的指令处继续执行。
- 在请求分页系统中,每当所要访问的页面不在内存时,便产生一缺页中断,请求 OS 将所缺之页调入内存。缺页中断作为中断,它们同样需要经历诸如保护 CPU 环境、分析中断原因、转入缺页中断处理程序进行处理、恢复 CPU 环境等几个步骤。但缺页中断又是一种特殊的中断,它与一般的中断相比,有着明显的区别,主要表现在下面两个方面:
- 地址变换机构
- 在检索块表和页表时,对于写指令,还须将修改位置成“1”。
- 缺页率
- 如果在进程的运行过程中,访问页面成功(即所访问页面在内存中)的次数为S,访问页面失败(即所访问页面不在内存中,需要从外存调入)的次数为F,则该进程总的页面访问次数为A = S + F,那么该进程在其运行过程中的缺页率即为
- 缺页率受以下因素的影响:
- 页面大小。
- 进程所分配物理块的数目。
- 页面置换算法。因此缺页率是衡量页面置换算法的重要指标。
- 程序固有特性。
- 事实上,在缺页处理时,选择被置换页面还需要考虑置换的代价,如页面是否被修改过。
页式虚拟存储管理机制的三种基本置换算法
最佳置换(OPT)算法选择的被淘汰页面,将是以后永不使用的,或许是在最长(未来)时间内不再被访问的页面;采用最佳置换算法可保证获得最低的缺页率。但是由于无法预知哪一个页面是未来最长时间内不再被访问的,因而该算法是无法实现的;
先进先出(FIFO)算法淘汰最先进入内存的页面,即选择在内存中驻留时间最久的页面予以淘汰。
最近最久未使用(LRU)算法根据页面调入内存后的使用情况进行决策,选择最近最久未使用的页面予以淘汰(向前);该算法赋予每个页面一个访问字段,用来记录一个页面自上次被访问一来所经历的时间T,当需要淘汰一个页面时,选择现有页面中T值最大的,即最近最久未使用的页面予以淘汰。
缺页次数:OPT:4次;FIFO:6次;LRU:4次
7.“抖动”与工作集
多道程序度与“抖动”
- 多道程序度与处理机的利用率
- 随着多道程序度的增大,处理机的利用率先上升后下降。当多道程序度过高时,会发生“抖动”。
- 产生“抖动”的原因
- 根本原因是,同时在系统中运行的进程太多,由此分配配给每一个进程的物理块太少,不能满足进程正常运行的基本要求,致使每个进程在运行时,频繁地出现缺页,必须请求系统将所缺之页调入内存。造成每个进程的大部分时间都用于页面的换进/换出,而几乎不能再去做任何有效的工作,从而导致发生处理机的利用率急剧下降并趋于0的情况。
工作集
- 工作集的基本概念
- 进程发生缺页率的时间间隔与进程所获得的物理块数有关(即成反比)。
- 基于程序运行时的局部性原理得知,程序在运行期间,对页面的访问时不均匀的,在一段时间内仅局限于较少的页面。这些页面被称为活跃页面。
- 工作集的定义
- 所谓工作集,是指在某段时间间隔Δ里,进程实际所要访问页面的集合。具体地说,把某进程在时间 t 的工作集记作 w(t, Δ),其中的变量 Δ 称为工作集的“窗口尺寸”。可将工作集的定义为,进程在时间间隔 (t-Δ, t) 中引用页面的集合。
- 工作集是窗口尺寸 Δ 的非降函数。即 w(t, Δ) ⊆ w(t, Δ+1)。
“抖动”的预防方法
这些方法几乎都是采用调节多道程序度来控制“抖动”发生的。
- 采取局部置换策略
- 即使该进程发生了“抖动”,也不会对其它进程产生影响,于是可把该进程“抖动”所造成的影响限制在较小的范围内。但在某进程发生“抖动”后,它还会长期处在磁盘 I/O 的等待队列中,使队列的长度增加,这会延长其它进程缺页中断的处理时间。
- 把工作集算法融入到处理机调度中
- 当调度程序发现处理机利用率低下时,它将试图从外存调入一个新作业进入内存,在从外存调入作业之前,必须检查每个进程在内存的驻留页面是否足够多。如果都足够多,此时便可以从外存调入新的作业,不会因新作业的调入而导致缺页率的增加;反之,如果有些进程的内存页面不足,则应首先为那些缺页率居高的作业增加新的物理块,此时将不再调入新的作业。
- 利用“L=S”准则调节缺页率
- 其中L是缺页之间的平均时间,S是平均缺页服务时间,即用于置换一个页面所需的时间。如果是L远比S大,说明很少发生缺页,磁盘的能力尚未得到充分的利用;反之,如果是L比S小,则说明频繁发生缺页,缺页的速度已超过磁盘的处理能力。只有当L与S接近时,磁盘和处理机都可达到它们的最大利用率。理论和实践都已证明,利用“L=S”准则,对于调节缺页率是十分有效的。
- 选择暂停进程
- 基于某种原则选择暂停某些进程。将它们调出到磁盘上,以便腾出内存空间分配给缺页率发生偏高的进程。