存储管理-页式管理
页式管理解决什么问题
- 分区式管理,存在着严重的碎片问题使得内存的利用率不高
1.固定分区,因为每一个分区只能分配给某一个进程使用,而该进程可能占不满这个分区,就会有内部碎片
2.动态分区,会产生大量的外部碎片,虽然可以使用紧凑技术,但是这样时间成本过高了
出现这种情况的原因是分区管理必须要求进程占用一块连续的内存区域,如果让一个进程分散的装入到不同的内存分区当中的话,这样就可以充分的利用内存,并且不需要紧凑这种技术了。比如把一个进程离散的拆分放到零散的内存碎片中去,这样就可以更为高效的利用内存。也就是产生了非连续的管理方式。
比如就是把一个进程拆分为若干部分,分别放到不同的分区中,比如一个进程23M,可以拆分为10M,10M,3M放到不同的分区中
如果分区分的更小,23M拆分为11个2M的,和一个1M的,每个分区是2M,那么总共会装满11个分区,剩下一个分区装不满,也仅仅浪费1M的空间,也就是分区越小的话,那么就是内存利用率就会越高。
- 分区式管理时,进程的大小受分区大小或内存可用空间的限制
- 分区式管理也不利于程序段和数据的共享
页式管理的改进
- 页式管理只在内存存放反复执行或即将执行的程序段与数据部分
- 不经常执行的程序段和数据存放于外存待执行时调入。
页式管理的基本概念
页框(页帧):将内存空间分成一个个大小相等的分区,每个分区就是一个页框。
页框号:每一个页框有一个编号,这个编号就是页框号,从0开始
页(页面):将进程分割成和页框大小相等的一个个区域,也叫页
页号:每一二个页面有一个编号,叫做页号,从0开始
注意:由于最后一个页面可能没有页框那么大,所以页框不可以太大,否则会产生过大的内存碎片
操作系统会以页框为单位为各个进程分配内存空间,进程的每一个页面分别放入一个页框中,也就是进程的页面和内存的页框具有一一对应的关系
注意:各个页面不需要连续存放,可以放到不相邻的各个页框中
如何实现地址的转化
1.首先需要知道一个进程内的页对应物理内存中的起始地址a是多少
2.其次要知道进程页内地址b是多少
3.逻辑地址对应的实际物理地址就是c=a+b
如何计算?比如逻辑地址80
确定页号:页号=逻辑地址/页面长度 1=80/50
页内偏移量:页内偏移量=逻辑地址%页面长度 30=80%50
每个进程页面对应物理内存中页框的首地址:这是通过页表查询到的,比如查询到对应物理内存首地址是4500
那么对应最终物理地址就是4500+30=4530
页表
页表的存在是为了让我们知道进程中的一个页的页号对应它存放在物理内存中的页框号,进而求出页框号对应的首地址
逻辑地址的结构
假如页号有k位,那么页数就是2^k个
假如页内地址m位,那么页内地址有2^m个
静态页面管理
在作业或进程开始执行之前,把作业或进程的程序段和数据全部装入内存的各个页面中,并通过页表(page mapping table)和硬件地址变换机构实现虚拟地址到内存物理地址的地址映射。
内存页面分配与回收
静态分页管理的第一步是为要求内存的作业或进程分配足够的页面。
依赖数据结构:
页表:
1.页表在内存中占有一块固定的存储区。页表的大小由进程或作业的长度决定。
2.对于一个每页长1K,大小为20K的进程来说,如果一个内存单元存放一个页表项,需要分配给该页表20个存储单元。
3.页式管理时每个进程至少拥有一个页表。
请求表:
1.用来确定作业或进程虚拟空间的各页在内存中的实际对应位置。为此,系统必须知道每个作业或进程的页表起始地址和长度。
2.此外,请求表还包括每个作业或进程要求的页面数。请求表整个系统一张
存储页面表:
记录内存各页面是否已被分配出去,以及未分配页面的总数。
位示图法:在内存中划分一块固定区域,每个单元的每个比特代表一个页面。如果该页面已被分配,则对应比特位置1,否则置0。
一个划分为1024个页面的内存,如果内存单元长20比特,则位示图要占据1024/20=52个内存单元。
空闲页面链法:
1.空闲页面链中,队首页面的第一个单元和第二个单元分别放入空闲页面总数与指向下一个空闲页面的指针。其他页面的第一个单元分别存放指向下一个页面的指针。
2.空闲页面链的方法使用空闲页面本身的单元存放指针,因此不占据额外的内存空间。
2.分配算法
1.首先,基于请求表获取进程或作业要求的页面数。
2.然后,基于存储页面表检查是否有足够的空闲页面。
3.如果没有,则本次无法分配。
4.如果有则分配设置页表,填写请求表中的相应表项;按一定查找算法搜索出所要求的空闲页面,并将对应的页面号填入页表中。
3.地址变换
地址变换过程全部由硬件地址变换机构自动完成。
设一个3页长的进程页号为0、1、2,其对应的页面号分别为2、3、8。设每个页面长度为1K,指令LOAD 1,2500的虚地址为100。
1.首先,需要一个保存页表始址和页表长度用的控制寄存器。系统把所调度执行的进程的页表始址和长度从请求表中取出置入控制寄存器中。
2.然后,由控制寄存器的页表始址,找到页表所在位置。并由虚地址100可知,指令LOAD 1,2500在第0页的第100单元。由于第0页与第2个页面相对应,因此,该指令在内存中的地址为2048+100=2148。
3.当CPU执行到第2148单元的指令时,CPU要从有效地址2500中取数据放入1号寄存器中。为了找出2500对应的实际物理地址,地址变换机构首先将2500转换为页号与页内相对地址组成的地址形式。即p=2,w=452。
4.由页表,可知第2页对应的页面号等于8。最后,将页面号8与页内相对地址w=452相连,得到待访问的物理内存地址8644。
快表:
取一个数据或指令至少要访问内存两次以上。
1.一次访问页表以确定所取数据或指令的物理地址
2.另一次是根据地址取数据或指令
提高速度:
1.把页表放在寄存器中,但寄存器价格太贵。
2.在地址变换机构中加入一个高速联想存储器,构成一张快表。在快表中,存入那些当前执行进程中最常用的页号与对应的页面号,从而提高查找速度。
静态页式管理的问题
动态页式管理分为请求页式管理和预调入页式管理。
1.由于静态页式管理要求进程或作业在执行前全部装入内存,如果可用页面数小于用户要求时,该作业或进程只好能等待。
2.而且,作业或进程的大小仍受内存可用页面数的限制。
动态页式管理
请求页式管理和预调入页式管理在作业或进程开始执行之前,不把作业或进程的程序段和数据段一次性地全部装入内存,而只装入经常反复执行和调用的工作区部分。其他部分在执行过程中动态装入。
请求调入
需要执行的某条指令不在内存,或执行某条指令需要访问的其他数据或指令不在内中,则发生缺页中断,系统将外存中相应的页面调入内存。
请求页式管理只允许进程或作业的部分程序和数据驻留在内存中,因此,执行过程不可避免地会出现某些虚页不在内存中的问题。
怎样发现不在内存中的虚页以及怎样处理这种情况,是请求页式管理必须解决的两个基本问题。
怎样发现不在内存中的虚页
扩充页表:即除了页面号之外,每个虚页号再增设该页是否在内存的中断位以及该页在外存中的副本起始地址。
虚页不在内存时的处理
1)采用何种方式把所缺的页调入内存。
根据内存中的程序是否被修改过,决定是否写回到外存。如何确定是否修改过,是通过页表新加的改变位
如果内存中被淘汰的某一页,曾因程序的执行而被修改,则该页应该重新写到外存上加以保存。而那些未被访问修改的页,因为外存已保留有相同的副本,没有必要写回外存。因此,在页表中还应增加一项以记录该页是否曾被改变。
2)如果内存中没有空闲页面,调进来的页放在什么地方。即采用什么策略淘汰已占据内存的页。
- 内存页面置换算法直接影响内存利用率和系统效率。
- 如果置换算法选择不当,有可能刚被调出内存的页又马上被调回内存,调回内存不久又马上被调出内存。
- 这使得整个系统的页面调度非常频繁,以致大部分时间花费在主存和辅存之间的来回调入调出上。这种现象被称为抖动(thrashing)现象。
整个流程:
- 其中有关地址变换部分由硬件自动完成。
- 当硬件变换机构发现所要求的页不在内存时,产生缺页中断信号,由中断处理程序做出相应的处理。
- 中断处理程序由软件实现。
请求调入的缺点:
请求页式管理是一个十分复杂的处理过程,牺牲系统开销提高内存利用率。
原因:除了在没有空闲页面时要按照置换算法选择被淘汰页面之外,还要从外存读入所需要的虚页。这个过程要启动相应的外存和涉及到文件系统。
请求页式管理中的置换算法
1.随机淘汰算法(random glongram):在无法确定哪些页被访问的概率较低时,随机选择某个用户的页面将其换出。
2.轮转法(round robin): 循环换出内存可用区内一个可以被换出的页,无论该页是刚被换进或已换进内存很长时间。
- 内存利用率不高
3.先进先出算法(FIFO):选择在内存驻留时间最长的一页将其淘汰。
- 内存利用率不高
- 陷阱现象:一般来说,给任一作业或进程分配的内存页面数越接近于它所要求的页面数,则发生缺页的次数会越少。极限情况下,这个推论是成立的。
使用FIFO算法时,在未给进程或作业分配足它所要求页面数的情况下,有时会出现分配的页面数增多,缺页次数反而增加的奇怪现象。这种现象称为Belady现象
Belady现象的例子:
设进程P有8页,且已在内存中分配3个页面,程序访问内存的顺序(访问串)为7,0,1,2,0,3,0,4,2,3,0,3,2,1,2,0,1。下表给出内存中进程P所建的程序和数据的各页面变化情况。
内存中给这个进程分配了三个页面,程序访问的页号依次是7,0,1,2,0,3,0,4,2,3,0,3,2,1,2,0,1
一开始的时候三个页面都是空的,它要求7号页,7号页不在内存中,所以要从外存调入一次缺页中断,0同理不在内存中调入,两次缺页了,1也不在,3次缺页,2页不在,但是现在内存满了,7由于最先到的,先淘汰它,2号进来,4次缺页,0号在内存中不发生缺页,之后依次是3,0,4,2,3,0,3,2,1,2,0,1号页。同理可得图片中黄色代表缺页了,缺页12次,访问17次,缺页率12/17=70.5%。
如果给进程P分配4个页面,则在其执行过程中内存页面的变化情况如下表所示。
进程P在拥有4个内存页面时,共发生9次缺页,其缺页率为9/17=52.9%。
设进程P可分为5页,访问串为1,2,3,4,1,2,5,1,2,3,4,5。当进程P分得3个页面时,执行过程中内存页面变化如下表所示。
进程P在执行过程中共缺页9次,其缺页率为9/12=75%。
如果为进程P分配4个内存页面,是否缺页率会变小呢?进程P分得4个页面时,执行过程中内存页面的变化情况如下表。
当
进程P分得4个页面时,执行过程中的缺页次数为10次。即缺页率=10/12=83.3%。
先进先出算法产生Belady现象的原因在于它没有考虑程序执行的动态特征。
4.最近最久未使用页面置换算法(least recently used)
基本思想:当需要淘汰某一页时,选择离当前时间最近的一段时间内最久没有使用过的页先淘汰。
该算法的主要出发点是,如果某页被访问了,则它可能马上还要被访问。或者反过来说,如果某页很长时间未被访问,则它在最近一段时间也不会被访问。
缺点:要完全实现LRU算法是一件十分困难的事情。因为要找出最近最久未被使用的页面,必须对每一个页面设置访问记录项,而且每一次访问都必须更新这些记录,这需要花费巨大的系统开销。因此,在实际系统中往往使用LRU的近似算法。
5.最不经常使用页面淘汰算法LFU(least frequently used)。
该算法在需要淘汰某一页时,首先淘汰到当前时间为止,被访问次数最少的那一页。
在页表中给每一页增设一个访问计数器即可实现。
某页被访问时,该页访问计数器加1,发生缺页中断时,淘汰计数值最小的那一页,并将所有的计数器清零。
6.最近没有使用页面淘汰算法NUR。
该算法在需要淘汰某一页时,从那些最近一个时期内未被访问的页中任选一页淘汰。在页表中增设一个访问位即可实现。
当某页被访问时,访问位置1。否则,访问位置0。
系统周期性地对所有访问位清零。
需淘汰一页时,从那些访问位为零的页中选一页淘汰。
7.理想型淘汰算法OPT(optimal replacement algorithm)
该算法淘汰在访问串中将来再也不出现的或是在离当前最远的位置上出现的页。
淘汰掉该页不会造成因需要访问该页又立即把它调入的现象。
这种算法无法实现,因为它要求必须预先知道每一个进程的访问串。
预调入
系统对外存中的页进行调入顺序计算,估计这些页中指令和数据的执行和被访问顺序,并按此顺序将它们顺次调入和调出内存。
页式管理存储保护
- 地址越界保护:地址变换机构中的控制寄存器的页表长度 VS. 要访问的虚地址。
- 存储控制保护:在页表中增加保护位用于控制内存信息的存取操作方式:。
页式管理的优缺点
优点:
- 不要求作业或进程的程序段和数据在内存中连续存放,有效地解决了碎片问题。
- 动态页式管理提供内存和外存统一管理的虚存实现方式,大大增加用户可以利用的存储空间。既提高了主存的利用率,又有利于组织多道程序执行。
缺点:
- 要求相应硬件支持。例如地址变换机构,缺页中断的产生等都要求有相应的硬件支持。增加了机器成本。
- 增加了系统开销,例如缺页中断处理等。
- 请求调页的算法如选择不当,有可能产生抖动现象。
- 虽然消除了碎片,但每个作业或进程的最后一页内总有一部分空间得不到利用。如果页面较大,这一部分的损失较大。