存储器管理
计算机的存储层次至少有三层,分别是寄存器、内存、外存。还可以根据具体功能划分为寄存器、高速缓存、内存、磁盘缓存、固定磁盘、可移动存储。
其中,寄存器、高速缓存、内存和磁盘缓存均属于操作系统存储管理的管辖范畴,断电后信息不再存在。固定磁盘和可移动存储介质属于设备管理的管辖范畴,它们存储的信息将被长期保存。
一、各种存储器
寄存器
寄存器的访问速度最快,与CPU相当,但价格昂贵,所以容量不会太大。寄存器的长度一般以字为单位。由于内存的访问速度远低于CPU执行指令的速度,为缓和这一矛盾,在计算机系统中引入了寄存器和高速缓存。
特点:快、贵、小
高速缓存
一般情况下程序的指令和数据放在内存中,但是由于内存的读取速度慢于CPU会导致运行效率低,所以引入了高速缓存。高速缓存的读取速度比内存快,价格比内存贵,所以容量比内存小。CPU访问信息时先到高速缓存中寻找,如果没有,再到内存中查找。一般计算机设有多级缓存。
内存
内存是计算机的重要部件,用于保存计算机运行的程序以及程序的数据。CPU只能从内存中读取指令和数据。
磁盘缓存
磁盘IO的速度远远低于内存的读取速度,所以在进行IO时会导致运行速度变慢,于是将一部分常用的磁盘数据放入内存中,减少磁盘访问量,提高CPU运行速度。磁盘缓存并不是一个实际存在的存储介质,只是对存放磁盘数据的内存的描述。
二、程序的装入与重定位
将一个用户源程序变成一个计算机可执行程序需要三步:
编译——>连接——>装入
编译:由编译程序将用户的源程序编译成若干个目标模块
链接:将这些目标模块所需的库函数用链接程序链接在一起,形成一个完成的装入模块
装入:使用装入程序将这些装入模块装入内存。
装入程序一般有三种装入方式:绝对装入方式、可重定位装入方式、动态运行时装入方式。
绝对装入
若编译时知道程序将驻留在内存的什么位置,则编译程序将产生绝对地址的目标代码。装人模块被装入内存后,由于程序中的逻辑地址与实际内存地址完全相同,故不须对程序和数据的地址进行修改。
绝对装入方式只能将目标模块装人到内存中事先指定的位置,因此只适用于单道程序环境。
可重定位装入(静态重定位)
在多道程序环境下,所得到的目标模块的起始地址通常从0开始,程序中的其它地址也都是相对于起始地址计算的,此时应采用可重定位装人方式,将装入模块装人内存的适当位置,这会使得装入模块中的所有逻辑地址与实际装人内存的物理地址不同,这个地址变换的过程称为地址重定位。因为把装入模块装入内存时,地址变换在装入时一次性完成,之后不再改变,故又称为静态重定位。
动态运行时装入(动态重定位)
可重定位装人方式并不允许程序运行时在内存中移动位置。而实际情况是,在运行过程中,程序在内存中的位置可能经常要改变,此时应采用动态运行时装入的方式:不在程序运行之前进行重定位,而是把这种地址转换推迟到程序执行期间进行,又称为动态重定位。
三、连续内存分配
连续内存分配是指给用户程序分配连续的内存空间。它可分为四种分配方式:单一连续分配、固定连续分配、动态分区分配、动态重定位分区分配。
单一连续分配
单一连续分配是最简单的内存分配方式,只能用于单用户、单任务的操作系统中。单一连续分配将内存分为系统区和用户区,系统区提供OS使用,用户区指系统区以外的所有内存,仅能存放一道程序。
固定分区分配
固定分区分配是最早的多道程序存储管理方式。固定分区分配是指将内存提前划分为若干个大小不等或相等的分区,一旦划好就不再改变,每个分区只能存放一个程序。
动态分区分配
动态分区分配是根据程序的需要动态的分配内存,在实现可变的分区分配时,涉及到分区分配中所使用的数据结构,分区分配算法和分区分配和回收三个问题。
分区分配的数据结构
为实现分区分配,系统中必须配置相应的数据结构,用来描述空闲分区和已分配分区的情况。常用的数据结构有以下两种形式:空闲分区表和空闲分区链。
分区分配算法
常用的分区分配算法有:首次适应算法、循环首次适应算法、最佳适应算法、最坏适应算法、快速适应算法。
1.首次适应算法
该算法将空闲分区按起始地址递增的次序排列,每次分配均从空闲分区表或空闲分区链首开始顺序查找,直至找到第一个能满足要求的空闲分区为止,并按作业的大小从该分区中分割出一块内存空间分配给请求者,剩余的部分仍留在空闲分区表或链中。该算法优先使用内存低址部分的空闲分区,从而能在高址部分保留较大的空闲分区,但它会在内存的低端留下很多难以利用的小空闲分区,而每次分配时,对空闲分区的查找都必须经过这些分区,从而会增加查找的开销。
2.循环首次适应算法
和首次适应算法的区别在于,循环首次适应算法查找空闲内存从上一次查找到的空闲内存的终止位置开始。所以循环首次适应算法减少了从头开始查找空闲位置的开销,但他会使内存中缺少大的空闲分区。
3.最佳适应算法
该算法将内存分区按容量大小递增的次序排列,每次查找都从空闲分区表或空闲分区链之首查找,并将第一个满足要求的空闲分区分配出去。虽然名字叫最佳,但是实际上会在内存中存在很多小的无法分配的内存分区。
4.最坏适应算法
最坏适应算法将内存分区按容量递减的次序排列,每次查找都从队首开始,如果要求的容量大于队首分区容量,则分配失败,如果满足要求,则分配成功,然后调整空闲分区链(表)。该算法的优点是产生碎片的几率最小,缺点是使内存中缺乏大的空闲分区
内存回收
当进程运行完毕释放内存时,需要进行内存的回收。系统根据回收区的首址,从空闲区链(表)中找到相应的插人点,此时可能出现以下几种情况:
1.回收区与插人点的前一个空闲分区F1相邻接。此时应将回收区与插人点的前一分区合并,不必为回收分区分配新表项,而只需修改其前一分区F1的大小。
2.回收分区与插人点的后一空闲分区F2相邻接。此时也可将两分区合并,形成新的空闲分区,但用回收区的首址作为新空闲区的首址,大小为两者之和。
3.回收区同时与插入点的前、后两个分区邻接。此时将三个分区合并,使用F1的表项和F1的首址,取消F2的表项,大小为三者之和。
4.回收区既不与F1邻接,又不与F2邻接。这时应为回收区单独建立一新表项,填写回收区的首址和大小,并根据其首址插入到空闲链中的适当位置。
可重定位分区分配
在动态分区分配方式中,经过一段时间的分配和回收后,内存中会产生很多小的空闲分区。此时,可能有用户程序因找不到足够大的空闲分区而难以装人,但所有空闲分区容量的总和却足以满足该程序的要求。
上述这些不能被利用的空闲分区可采用以下办法加以解决:将内存中的所有作业进行移动,从而将原来分散的多个空闲分区移到同一处拼接成一个大的空闲分区,以装入用户的作业。这种技术被称为“拼接”或“紧凑”
可重定位分区分配方式就是在动态分区分配方式的基础上增加紧凑功能,即在找不到足够大的空闲分区、而空闲分区总和却能满足用户的要求时,对内存空间进行紧凑。由于紧凑时,作业要在内存中移动位置,因此,它需要得到动态重定位技术的支持,这也是它被称为动态重定位分区分配的原因。
四、离散内存分配
连续分配方式会形成许多“碎片”,虽然可通过“紧凑”方法加以解决,但须为之付出很大开销。因此,OS中又引入了离散分配方式,它将一个作业离散地存放到内存中,从而使系统无须紧凑便能很好地解决碎片问题。
如果离散分配的基本单位是页,则称为分页存储管理方式;如果离散分配的基本单位是段,则称为分段存储管理方式。
分页存储管理
分段存储管理
五、虚拟存储管理
局部性原理
程序局部性原理是指程序在执行时将呈现出局部性规律,即在一较短时间内,程序的执行仅局限于某个部分;相应地,它所访问的存储空间也局限于某个区域。
局限性还表现在下述两方面:
时间局限性:
如果程序中的某条指令一旦执行,则不久以后该指令可能再次执行;如果某数据被访问过,则不久以后该数据可能再次被访问。产生时间局限性的典型原因是由于在程序中存在着大量的循环操作。
空间局限性:
一旦程序访问“了某个存储单元,在不久之后,其附近的存储单元也将被访问,即程序在一段时间内所访问的地址,可能集中在一定的范围之内,其典型情况便是程序的顺序执行。
基于局部性原理产生了虚拟存储器。
虚拟存储器的实现
虚拟存储器是指具有请求调入功能和置换功能,能从逻辑上对内存容量加以扩充的一种存储器系统。虚拟存储器中存放的是进程中的目标代码、数据等虚拟地址组成的虚拟空间。
虚拟存储器不考虑物理存储器的大小和信息存放的时机位置,只规定每个进程中相互关联信息的相对位置。与实际物理存储器数量有限,且被所有进程共享不一样,每个进程都拥有自己的虚拟存储器。
虚拟存储器的逻辑容量由内存容量和外存容量之和所决定,受计算机地址结构的限制,其运行速度接近于内存速度,而每位的成本却又接近于外存。
虚拟存储器的实现,建立在离散分配的存储管理方式的基础上。目前,虚拟存储器主要是采用下述方式之一实现的:
请求分页系统:
在分页系统的基础上,增加了请求调页功能和页面置换功能,便形成页式虚拟存储系统。它允许只装人少数页面的程序及数据,便启动运行。之后再通过调页功能及页面置换功能,陆续地把即将要运行的页面调人内存,同时把暂不运行的页面换出到外存上。
请求分段系统:
在分段系统的基础上,增加了请求调段及分段置换功能后,便形成段式虚拟存储系统。它允许只装人少数而非所有段的用户程序和数据,即可启动运行。之后再通过调段功能和段的置换功能将暂不运行的段调出,同时调人即将运行的段。
请求段页式系统:
段页式虚拟存储器是段式虚拟存储器和页式虚拟存储器的结合。它把程序按逻辑单位分段以后,再把每段分成固定大小的页。主存空间也划分为若千个同样大小的页。虚存和实存之间以页为基本传送单位,每个程序对应一个段表, 每段对应一个页表。虚地址包含段号、段内页号、页内地址三部分。CPU访问时,首先将段表起始地址与段号合成,得到段表地址,然后从段表中取出该段的页表起始地址,与段内页号合成,得到页表地址,最后从页表中取出实页号,与页内地址拼接形成主存实地址。
虚拟存储器的特征
虚拟存储器具有多次性、对换性、虚拟性三大主要特征。
多次性:多次性是指虚拟存储器将一个作业分多次调入内存。
对换性:在作业运行期间,虚拟存储器允许将内存中暂时不能运行的进程或暂时不用的程序或数据,调出到外存上,以便腾出足够的内存空间,再把具备运行条件的进程或进程所需要的程序和数据调入内存。
如果对换是以整个进程为单位的,便称之为“整体对换”或“进程对换"。这种对换被广泛地应用于分时系统中,其目的是用来解决内存紧张问题,并可进一步提高内存的利用率。而相应的,**如果对换是以“页”或“段”为单位进行的,则分别称之为“页面对换”或“分段对换”,又统称为“部分对换”。**它们是实现虚拟存储器的基础。
虚拟性:虚拟性是指能够从逻辑上扩充内存容量,使用户所看到的内存容量远大于实际内存容量。虚拟性是实现虚拟存储器的最重要的目标。
虚拟性是以多次性和对换性为基础的,仅当系统允许将作业分多次调入内存,并能将内存中暂时不运行的程序和数据换至盘上时,才有可能实现虚拟存储器;而多次性和对换性又必须建立在离散分配的基础上。
六、页面置换算法
置换算法的好坏直接影响系统的性能。若采用的置换算法不合适,可能出现这样的现象:刚被换出的页,很快又被访问,为把它调入而换出另一页,之后又访问刚被换出的页…如此频繁地更换页面,以致系统的大部分时间花费在页面的调度和传输上。此时,系统看起来很忙,但实际效率却很低。这种现象称为“抖动”。好的页面置换算法能够适当降低页面更换频率(减少缺页率),尽量避免系统“抖动”。为评价一个算法的优劣,可将该算法应用于一个特定的存储访问序列上,并且计算缺页数量,存储访问序列也叫页面走向。
最佳置换算法(OPT)
最佳置换算法(Optimal,OPT)是选择不再访问的页面或者是在未来最长时间内不再被访问的页面予以淘汰。最佳页面置换算法是在理论上提出的一种算法,具有最好的性能,但实现是困难的,因为它需要人们预先知道一个进程在整个运行过程中页面走向的全部情况。不过这个算法可用来衡量其他算法的优劣。
缺页中断的次数/访问序列数量=缺页率
先进先出页面置换算法(FIFO)
FIFO算法总是淘汰最先进人内存的页面,即选择在内存中驻留时间最久的页面予以淘汰,该算法的出发点是最早调人内存中的页面,其不再被使用的可能性会比较高。其实现简单、直观,对按线性顺序访问的程序比较合适,面对其他情况则效率不高,因为经常被访问的页面,往往在内存中因停留得最久而被淘汰。
FIFO算法存在一个问题,一般情况下,能够分配的物理块的个数越多,缺页次数应该越少,但是FIFO存在Belady现象(增加物理块,缺页次数可能多也可能少)。
增加一个物理块,却也次数反而变多了。
最近最久未使用算法(LRU)
LRU算法是根据页面调入内存后的使用情况进行决策的。由于无法预测各页面将来的使用情况,只能以“最近的过去”作为“最近的将来”的近似,选择在最近一段时间里最久没有使用过的页面予以置换。因此,LRU算法是与每个页面最后使用的时间有关的,当必须置换一个页面时,LRU算法选择过去一段时间内最久未使用的页面。
对于前面的样例,下表列出了物理块数为3时的页面置换情况,缺页次数为10,
缺页率为10/12≈83%。