为什么有页式管理?
因为分区式管理本身的局限性
第一,导致内存中存在很多小碎片,使得内存利用率不高
第二,进程的大小收到分区后的区块大小限制
第三,分区后的各个区之间不能实现共享
基于上述三个管理的问题
于是,有人推出了页式管理
那么,什么页式管理?
目录
一、什么是页式管理?
页式管理和分区管理一样
本质是一种对内存的管理方式
为什么要对内存进行管理?
为了更好的利用内存,提供更好的服务
对内存进行组织的前提,是对内存进行描述
先描述,再组织
如何描述内存?
1、将进程的虚拟空间划分为若干个长度相等的页(page)
页长的划分和内存、外存之间的数据传输速率以及内存大小有关
2、一般每个页长度为1K~4K之间
3、经过划分后,进程虚拟地址变为页号P+页内地址构成
以下是一个页长为1K的虚拟地址结构示意图:
除此之外,把内存也划分为页,称为页面
于是:页数×页大小 = 内存大小
内存中,除了操作系统占用的页之外,其余页提供给任何进程共享
而用户的进程在内存中占用的页是不连续的,哪个空闲用哪个
经过上述的内存划分描述,
克服了分区管理的困难:
1、小碎片减少,任何一个小碎片都会小于一个页面
2、进程地址支持不连续存储
注意:(可看可不看,博主自己的理解)
这里要深刻理解为什么分区式管理导致碎片多,而页式管理又减少外部碎片?
1、分区式管理导致碎片多的原因:
对于固定分区法:
一个连续的空间,划分为一个个大小不一的块
一个进程占用一个块,而不是多个块
于是,一个块被占用后剩余的小空闲块,如果前后没有相邻空闲块
这一小块就会单独称为一个空闲块
该空闲块和其他任何大空闲块一样,
以平等的身份作为进程分配的单位块
于是,很明显,该块由于小
很可能就会因为大小不满足需求而不会被分配
对于动态分区法:
尽管动态分区法不提前划分区
而是按照进程需求,按需分配
似乎不会产生小碎片
但是在资源回收时
依旧会在中间部分产生空闲块:
因此,由于分区式管理的机制
导致内部小空闲片又会以单独的姿态插入到可用表 / 自由链中
从而称为外部碎片
无论是固定分区法还是动态分区法都无法避免外部碎片
从而导致内存的浪费
什么叫做外部碎片?
单独作为分配进程的内存块单位称为外部碎片
什么叫做内部碎片?
一个空闲块被占用后,没有用完
剩余的部分叫做内部碎片
2、为什么页式管理会减少碎片的产生呢?
本质是因为单位划分和分配机制
把内存划分为一个一个的页面
页面大小固定
对于一个进程,你要几个页面,我就给你几个页面
我不管这几个页面在哪里,连续还是不连续
我只管页面是否空闲可用
这种方式虽然依旧会内部碎片的产生
为什么?
例如,一个进程需要的大小是1.9个页面的大小
我只能给他2个页面
此时,剩余的0.1个页面不能作为单独的页面
只能浪费
但是,这种管理方式将不会再产生外部碎片
因此,从上述的分析中,我们可以知道:
页面分的越小,内存浪费也就越小
但是,伴随而来的是页面分配的消耗
因此,页面的划分需要综合考量
二、静态页式管理
页式管理又分为静态和动态之分
这里首先介绍静态页式管理
什么是静态页是管理?
在进程执行前,将其所有的程序和数据装入内存的各个页面中
(内存中划分的页叫做页面)
1、内存页面的分配与回收
我们已经知道了内存页面是如何划分
已经描述好了,怎么组织呢?
先描述,再组织
需要一些额外的数据结构进行组织
这里是页表、请求表、存储页表
1)页表
最简洁的页表:页号 + 页面
一个进程至少一个页表
页表在内存占有一个固定的存储区域
页表的大小由进程的大小决定
例如:
一个内存单元存放一个页表项目
(一个页表项目由一个页号+一个页面构成)
如果一个进程需要20个页面
那么页表就应该有20个项
需要分配给页表20个内存单元
以下是一个页表示例图:
2)请求表
用于确定:进程的虚拟空间的各页在内存中的实际地址
如:进程所需求的页面数、进程号、
进程页表在内存的起始地址、页表长度、页面状态
一个系统一张请求表
如图:
3)存储页面表
一个系统一个存储页面表
指明各内存中各个页面分配状态
有两种方法:
一、位示图法
在内存中划分一个固定区域
该区域每一个bit位,对应整个内存中对应页面
如果对应页面被分配,对应bit位设为1,否则为0
逻辑图如下:
二、空闲页表法
其组织方法是:
将所有的空闲页表链接起来
形成一个空闲页表链
队头第一个单元记录空闲页面数量
队头第二个单元记录下一个空闲页面开始地址
其他页面的第一个单元记录下一个空闲页面的开始地址
位示图法需要额外占用一块内存空间
但是空闲页表法就不需要,因为使用了空闲页表本身的空间
(事实上这么说是不严谨的,因为始终要占用空间的,只是分散了而已)
2、如何分配?如何回收?
分配:
第一,请求表给出进程要求的页面数量
第二,由存储页表检查是否有足够的空闲页面,有则分配,没有则失败返回
第三,查找算法查找空闲页面,将页面填入页表中,并更新被分配页面状态为已分配
以下是分配算法流程图:
回收:
回收很简单
更新对应页表项
将被释放页面状态设置为未分配 / 插入空闲页面链
3、地址变换(重点!!!)
如何由页号页内相对地址变换到实际内存地址?
首先,需要装有页表起始地址和页表长度的控制寄存器
(系统从请求表中将页表起始地址和页表长度调入控制寄存器)
第一、由于控制寄存器页表起始地址可知页表在内存地址
第二、根据虚地址,计算出相对页号,从页号找到所对页面
第三、物理地址 = 页面号起始地址 + 虚拟地址
例如:指令LOAD 1 ,2500,其虚地址为100,页面大小为1K
通过下图找到其物理地址:
1、虚地址为100,页号为0
2、0页号对应页面2,于是物理地址 = 1024×2 + 100 = 2148
3、当执行到该指令时,意为从2500虚拟地址中取数据,放到1号寄存器中
4、怎么找?同样的,2500转化为页号和页内相对地址
5、2500 - 1024 × 2 = 452
6、2500虚拟地址在2号页,页内相对地址为452,对应页面8
7、于是,物理地址 = 1024 × 8 + 452 = 8644
根据上述过程,取一个数据 / 指令至少需要访问内存2次
一次为确定指令内存地址去执行指令,第二次为根据指令操作取到相应数据
访问2次,慢,怎么办?
方法一是加入寄存器,但是贵
方法二是加入高速存储器,放经常访问的页号
三、动态页式管理
1、概述
动态管理是在静态的基础上延伸出来的
动态页式管理在进程执行前,不将所有程序和数据调入内存
而是将被认为是经常 和 反复执行的程序段和数据页调入内存
动态页式管理又分为:请求页式管理 和 预调入管理
请求页式管理:
当执行时,发现程序 / 数据不在内存,则缺页,从外存调入相关页面
执行->不在内存->缺页->调入
预调入管理:
执行时,先估计各个页之间的执行顺序
之后按照顺序依次调入内存执行
上述两者之间,除了预调入需要排序外,其余机制基本相同
下面主要介绍请求调入管理
2、请求调入管理
1)地址变换问题
虚拟地址->物理地址变换
和静态页式管理一样
物理地址 = 页面号起始地址 + 页内相对地址
2)缺页问题
由于请求调入管理没有将所有页调入内存,
如果发生缺页,怎么办?
以及,我怎么知道这个页缺了没有?
为了解决这两个问题
需要对页表加入新的管理数据
例如,
标记页面是否缺页的 ”中断位“
缺页需要从外存调入,因此需要加入缺页的”外存起始地址“
下面是加入”中断位“ 和 ”外存起始地址“的页表:
同时,缺页以后,要从外存调入
这涉及:怎么调入的问题?
如果内存不够了,怎么办?
要把内存中的部分页干掉,抽出空闲空间
干掉谁?
如果要干掉的页有数据被修改了(没有修改则不需要管)
需要刷新到外存,否则别人的进程数据就被你干掉了
那么,我怎么知道这个页有没有被修改呢?
因此,要在页表中加入一个新的管理数据:”改变位“
以标志被置换出内存的页是否需要刷新到外存
以下是加入”改变位“的页表:
因此,关于缺页的调入和调出,
当内存不够时,主要涉及内存置换策略的问题
如果策略不得当,会导致刚被换出的内存页又被调入内存
如此反复,增加开销,效率低下
这种现象叫做”抖动“
下面是动态页式管理的流程图:
四、请求页式管理中的置换算法
1、随机淘汰算法
很简单,我不知道该换谁,那就随机,看命
2、轮转法
循环换出内存中一个可以被换出的页,不管该页刚被换进内存还是换进内存很久
山水轮流转,这次你滚,下次他滚出内存,一视同仁
3、先进先出算法
换出最先调入内存的页
该算法认为最先调入的页不再被访问额的可能性最大
这种思想的基础是,认为计算机的执行是线性的
但是事实上并非如此,例如循环
实现FIFO算法,需要一个队列
各个页按照调入时间长短进行顺序链接
每一次要置换页,就将队头换出,新调入页插入队尾即可
一般来说,一个进程被分配的页数越接近需求页
那么缺页越少,比如你要10页,我给你10页,根本不会发生缺页
但是,对于先进先出算法来说
在未分配满足需求的情况下
当给予的页数越多,反而会出现缺页次数越多的现象
该现象叫做陷阱现象
陷阱现象
缺页率:缺页访问次数 / 总访问次数
博主这里不做对比,仅仅讲解缺页率的计算方法
会算缺页率,一对比,就知道是否是陷阱现象
示例:
一个进程P有5页,内存分配3页
访问页队列为:1、2、3、4、1、2、5、1、2、3、4、5
执行过程为:(划红线部分为缺页项)
(如图)
陷阱最主要的原因,
是因为没有考虑到程序执行的动态特征,仅认为是线性的
这样导致刚换掉的页恰好是后面要访问的页
这就像我们平时解决问题,需要考虑的因素不能单一化,需要多角度综合考量
4、最近最久未使用算法
淘汰当前一段时间内,最久没有被使用过的页
算法的思想基础,是认为如果某页很久没有被使用,那么最近也不会被使用
实际的算法实现比较复杂
一般使用近似算法,有两种:
1)最不经常使用算法
每次淘汰截至当前时间访问次数最少的页
算法实现也很简单
在页表中增加一个访问计数器
每访问依次,计数器+1,每次淘汰计数器最少的页
而后更新所有计数器,全部置为0
2)最近没有使用算法
淘汰最近一个时期,没有被访问过的页
算法实现:
在页表中增加一个访问位即可
从所有访问位为0的页中,随机删除一个页
5、理想型淘汰算法
淘汰今后不会再访问的页 和 离当前执行最远的页
这种算法无法实现
因为需要知道整个进程的执行页序列
(1.5语,不能实现你说个毛线...)
五、存储保护
页式管理可为内存提供两种保护:
1、地址越界保护
当要访问页内地址,进行检查是否越界
2、存取控制
当要存取页内数据时,增加权限限制
在页表增加一个保护位即可
六、页式管理优缺点
优点:
1)避免外部碎片问题
2)动态页式管理将内存和外存统一管理, 实现虚拟存储, 增加可利用空间, 提高利用率
缺点:
1)需要硬件, 如控制存储器, 增加成本
2)增加系统开销, 例如缺页中断处理