存储器管理
存储器的层次结构
- 存储器的层次结构:寄存器-高速缓存-主存-磁盘缓存-磁盘-可移动存储介质
- 可执行存储器:寄存器和主存:存放于其中的数据只需要load或者store指令即可或者
- 对于辅存的访问需要I/O设备的参与,将涉及到中断、设备驱动、以及物理设备的运行,消耗时间比较多
- 存储器管理主要负责对可执行存储器的分配、回收以及提供在存储器层次间数据移动的管理机制
- 主存储器:用于保存运行时的程序和数据,CPU控制部件只能从主存储器中取得指令和数据,数据能够从主存储器读取并且装入到寄存器中,或者从寄存器存入到主存储器
- 寄存器:寄存器访问速度最快,与CPU接近,用于加速存储器的访问速度:如通用寄存器存放操作数,或者用地址转换寄存器加快地址转换速度等
- 高速缓存:容量远大于寄存器,但比内存小两到三个寄存器,根据局部性原理,将主存中经常访问到的信息存放在高速缓存中,用于减少对主存的访问次数
- 磁盘缓存:I/O的速度远低于主存的访问速度,所以经常将一部分频繁使用的磁盘数据存放在磁盘缓冲中,可以减少磁盘的访问次数,利用主存中的存储空间,来暂时存放从磁盘中读取的数据(也可以说主存就是辅存的高速缓存)
程序的装入和链接
-
程序的装入
- 绝对装入方式
- 编译时,直接产生绝对地址,绝对装入程序按照装入模块中的地址,将程序和数据进行装入,装入后,程序中的逻辑地址与实际内存地址完全相同
- 只能将目标模块装入到内存中事先指定的位置,只适用于单道程序环境
- 可重定位装入方式
- 多道程序环境中,所得到的目标模块的起始地址通常是从0开始,装入内存时,所有地址需要根据程序装入的首地址进行重新修改,由于地址是在装入时一次性完成的,以后不再改变,故也称为静态重定位方式
- 不允许在运行时在内存中移动位置(此时的所有地址已经转化为绝对地址了)
- 动态运行时装入方式
- 将装入模块装入内存后,并不直接将相对地址转化为绝对地址,而是将地址转换推迟到程序真正要执行时才进行,所以,装入后的地址依旧是相对地址,但需要提供一个重定位寄存器,用于加快地址转换的速度
- 绝对装入方式
-
程序的链接
- 静态链接
- 程序运行之前,将各个目标模块以及它们所需要的库函数,链接成一个完整的装配模块,以后不再拆开
- 装入时动态链接
- 装入内存时,边装入边链接
- 运行时动态链接
- 运行时需要该模块,再进行链接
- 静态链接
连续分配方式
- 连续分配方式:为一个用户分配一个连续的内存空间
-
单一连续分配
- 只能用于单用户、单任务的操作系统中
- 把内存分为系统区和用户区
-
固定分区分配
- 最简单的可运行于多道程序的内存管理方式,将内存用户空间划分为若干个固定大小的区域,每个分区中只能装入一道作业
- 适用于控制多个相同对象的控制系统中
- 划分分区的方法
- 分区大小相等
- 所有的内存分区大小相等
- 缺乏灵活性
- 分区大小不等
- 将内存分区划分为多个较小分区、适量的中等分区以及少量的大分区
- 分区大小相等
- 内存分配
- 将分区按大小进行排队,并为之建立一张分区使用表,各表项包括:每个分区的起始地址、大小以及状态,分配时扫描该表,找到满足对应项则进行分配
-
动态分区分配
- 根据进程的实际需要,动态为其分配内存空间
- 分区分配中的数据结构
- 空闲分区表:系统中设置一张空闲分区表,用于记录每个分区的使用情况,每个分区占一个表项,包括:分区序号,分区起始地址,分区的大小等数据项
- 空闲分区链
- 分区分配算法
- 首次适应算法(FF)
- 要求空闲分区链按照地址递增的次序链接,分配内存时,从链首开始顺序查找,直到找到满足为止
- 循环首次适应算法(next fit)
- 分配空间时,从上一次找到的空闲分区的下一空闲分区开始查找,直到找到一个满足要求的空闲分区
- 最佳适应算法(best fit)
- 将所有空闲分区按照其容量从小到大的顺序形成一空闲分区链,找到大小刚刚好的分区进分配
- 最坏适应算法(worst fit)
- 扫描整个分区表,挑选最大一个空闲分区进行分配
- 快速适应算法(quick fit)
- 将空闲分区根据其容量的大小进行分类,对每一类具有相同容量的所有空闲分区,单独设置一个空闲分区链表,同时设置一张管理索引表,每一个表项对应一个空闲分区链
- 首次适应算法(FF)
- 分区分配操作
- 分配内存
从空闲分区表中查找分区,如果满足,则将其分配出去(如果剩余大小小于预定大小,则直接分配,而不分割该分区,否则,分割该分区) - 回收内存
- 如果插入点与回收分区相邻,则将其合并即可
- 如果不相邻,则在空闲链中新建项,并且填写相关信息
- 分配内存
- 伙伴系统
- 无论已经分配的分区还是空闲分区,其大小均为2的k次幂( 1 <= k <= m ,其中1表示最小分配,m表示最大分配,通常m为整个可分配内存空间的大小),将空闲分区根据分区大小进行分类,对于每一类具有相同大小的所有空闲分区,单独设置一个空闲分区双向链表,这样,空闲分区形成k个空闲分区链表
- 当需要分配大小为n是,先计算2^(i-1) <= n <= 2^i,然后在i链表里查找,找到则分配,找不到则在i+1链表中查找,并且现将i+1分区分为两个大小i的分区,一个用于分配,一个用于加入i链表
- 回收时也需要多次合并,如果存在i,则将其余回收的i合并到i+1中
-
动态重定位分区分配
- 紧凑/拼接:通过移动内存那种作业的位置,把原来多个分散的小分区拼接成一个大分区的方式,每次紧凑之后,都需要对移动了的程序或者数据进行重定位
-
对换:把内存中暂时不能运行的进程或者暂时不用的程序和数据调出到外存上,以便腾出足够的内存空间,再把已具备运行条件的进程或进程所需要的程序和数据调入内存
- 整体对换/进程对换
- 页面对换/分段对换
- 对换空间的管理
- 把外存分为文件区(离散分配)和对换区(连续分配),前者用于存放文件,后者用于存放从内存中换出的进程
- 系统应该配置相应的数据结构,用于记录外存的使用情况:空闲分区表/空闲分区链,保存两项内容:对换区的首址(盘块号)及大小(盘块数)
- 进程的换出与换入
- 进程的换出:选择处于阻塞态且优先级最低的进程作为换出进程,然后启动磁盘,将该进程的程序和数据传送到磁盘的对换分区上,如果传送过程未出错,则回收该进程所占空间,并且对该进程的进程控制块做出相应的修改
- 进程的换入:系统应该定时查看所有进程的状态,从中找出就绪状态但已换出的进程,将其中换出时间最长的进程换入内存
-
基本的分页存储管理方式
页面和页表
- 页面
- 页面和物理块
- 分页存储管理是将一个进程的逻辑地址空间分成若干个大小相等的片,称之为页面或者页,并且为各页编号,相应的,也把内存空间分成与页面大小相同的若干个存储块,称之为物理块或者页框,同样为其编号,为进程分配内存时,以块为单位将进程中的若干页分别装入到多个可以不相邻的物理块中,由于进程的最后一页经常装不满一块而形成不可利用的碎片,称之为页内碎片
- 页面大小:页面大小应该适中,且大小应该是2的幂,通常是512B~8KB
- 页面和物理块
- 地址结构:分为两个部分(页号P以及位移量W(页内地址))
- 页表:为了保证进程能够正确的运行,也就是能在内存中找到每个页面所对应的物理块,系统需要为每个进程建立一个页表,记录了进程空间中所有页以及其对应的物理页的情况
地址变换机构
- 基本的地址变换机构
- 在系统中设置一个页表寄存器,存放页表在内存中的起始地址和页表的长度,未执行时,该信息保存在PCB中,调度时,将其装入页表寄存器
- 查找时,先根据逻辑地址以及页表地址(页表寄存器)得出对应页表项的地址,然后读取其内容,获得对应的物理块,然后再通过计算,得到对应的物理块地址
- 具有快表的地址变换结构
- 快表TLB:用于存放当前访问的页表项
- 查找时,先看当前快表中是否有该项,如果有,则直接使用该项,如果没有,则按照前面内容查找,然后将其缓存在快表中
- 两级和多级页表
外层页表中存放内层页表的物理地址,借助外层页表寄存器即可读出外层页表的,然后计算得到内层页表,然后可以去取出对应的物理块地址
基本分段存储管理方式
- 引入分段存储管理方式的目的
- 方便编程:将作业进行分段,每个段都是从0开始,并且有自己的长度以及名字
- 信息共享:段的共享
- 信息保护
- 动态增长:段的长度可以自由变换
- 动态链接
分段系统的基本原理
- 段地址结构:段号 段内地址
- 段表:系统为每个段分配一个连续的分区,而进程中的各个段可以离散地移入不同的分区中
分段与分页的区别
- 页是信息的物理单位,分页是为实现离散分配方式,以消减内存的外零头,提高内存的利用率,分页仅仅是系统管理的需要而不是用户的需要,段是信息的逻辑单位,它含有一组意义相对完整的信息,分段的目的是为了更好地满足用户的需要
- 页的大小固定且由系统决定,在系统中只能有一种大小的页,段的长度是不确定的,主要取决于用户的程序,通常由编译程序在对源程序进行编译时,根据信息的性质划分
段页式存储管理
- 基本原理:分段和分页的结合,先将程序进行分段,再把每个段分成若干个页,并为每个段赋予一个段名
虚拟存储器的基本概念
常规存储器管理的特征
- 一次性:要求将作业全部装入内存后才能运行
- 驻留性:作业装入内存后,便一直驻留在内存中,直至作业运行结束
虚拟存储器:具有请求调入和置换功能,能从逻辑上对内存容量加以扩充的一种存储器系统,其逻辑容量由内存容量和外存容量之和所确定,其运行速度接近于内存速度,而成本接近于外存。
虚拟存储器的实现方法
- 分页请求系统:在分页系统上增加了请求调页功能和页面置换功能,陆续地把要运行的页面调入内存,同时把暂时不用的页面换到外存上,置换时可以以页面为单位
- 硬件支持
- 请求分页的页表机制
- 缺页中断机制
- 地址变换机构
- 实现请求分页的软件
- 硬件支持
- 请求分段系统:以分段机制为基础,置换时以段为单位
- 硬件支持
- 请求分段的段表机制
- 段中断机构
- 地址变换机构
- 硬件支持
虚拟存储器的特征
- 多次性:一个作业被分成多次调入内存
- 对换性:允许作业在运行过程中进行换进换出
- 虚拟性:从逻辑上扩充了内存容量
请求分页存储管理方式
请求分页的硬件支持
- 页表机制:将用户空间的逻辑地址变换为内存空间中的物理地址,需要多记录状态位,访问字段,修改位,外存地址
- 缺页中断机制:一条指令在执行期间可能会发生多次缺页中断,系统必须保证能保持多次中断的状态,并且保证最后能返回到中断前产生缺页中断的指令处继续执行
- 地址变换机构
内存分配策略和分配算法
- 最小物理块的确定:保证进程正常运行所需的最小物理块
- 物理块的分配策略
- 固定分配局部置换
- 可变分配全局置换
- 可变分配局部置换
- 物理块的分配算法
- 平均分配算法
- 按比例分配算法
- 考虑优先权的分配算法
调页策略
- 请求页面的时机
- 预调页策略:预计在不久之后需要访问的页面预先调入内存
- 请求调页策略:运行时根据需要调入
- 确定从何处调入页面
- 系统拥有足够的对换区空间,可以全部从对换区调入所需页面(在运行之前,须将有关的文件从文件区拷贝直对换区)
- 系统缺乏足够的对换空间:凡是不会修改的文件从文件区调入,可能修改部分,须将其调入到对换区
- Unix方式:与进程有关的文件都放在文件区,凡是未运行过的页面,都应该从文件区调入,对于运行过但又被换出的页面,存放在对换区
- 页面调入过程
- 未存在,则发出缺页中断,交给中断处理程序处理,进行调入,修改等操作
页面置换算法
最佳优先置换算法
最佳优先置换算法是一种理想的算法,实际上很难实现,基本思想是:每次选择以后不会再使用的页面,或者是在最长未来时间内不再被访问的页面进行替换
先进先出页面置换算法
思想:淘汰最先进入内存的页面,也就是选择在内存中驻留时间最久的页面
最近最久未使用置换算法(LRU Least Recently Used)
思想:为每个页面添加一个访问字段,用来记录一个页面自上次被访问以来所经历的时间t,当淘汰一个页面时,选择现有页面中其中t值最大的,即最近最久未使用的页面进行替换
需要硬件
- 寄存器:为每个页面设置一个计数寄存器,每隔一定时间向右移动一位,替换时选择值最小的页面进行替换
- 栈:用于保存当前使用的各个页面的页面号
Clock置换算法
由于LRU算法要求要有比较多的硬件支持,所以实际中不经常使用,一般使用其替代算法如Clock算法等
- 简单的Clock置换算法
- 为每个页设置一个访问位,在将内存中所有页面都通过指针链接成一个循环队列,每次从队首开始检查,如果发现访问位为1,则将其设置为0,如果是0,则替换该页,如果循环一遍还没有找到,则再循环一次
- 改进型Clock算法
- 增加多一个置换代价,通过组合,有四种情况,如下
- (A = 0, M = 0):表示既没有被访问过,也没有被修改过,最佳的淘汰页
- (A = 0, M = 1):未被访问过,但是已经被修改过,不是很好的淘汰页
- (A = 1, M = 0):被访问过,但是未被修改过,有可能再被访问
- (A = 1, M = 1):既被访问过,也被修改过,可能再被访问
- 执行过程
- 循环扫描,寻找A = 0, M = 0 的页面,如果遇到,则选择替换,第一次扫描不改变A
- 如果1失败,也就是查找一周之后没有找到第一类页面,则开始第二轮扫描,寻找A = 0并且M = 1的页面,将遇到的第一个作为淘汰页,并且将所有扫描过的访问位设置为0
- 如果2也失败,则将所有访问位设置为0,然后重复1,然后再重复2
- 增加多一个置换代价,通过组合,有四种情况,如下
最少使用算法(LFU Least Frequently Used)
基本思想同LRU
页面缓冲算法(PBA)
思想:使用两个队列,一个空闲一个存放页面,等到一定数量再将其写入到磁盘上
请求分页存储管理方式
请求分段的硬件支持
- 段表机制:增加一些项,如:存取方式,访问字段,修改位,存在位,增补位,外存地址
- 缺段中断机构
- 地址变换机构