第四章 存储器管理
存储器是计算机的重要组成部分。五大组成部分
存储器容量很大,但仍不满足用户需要。
存储器管理方式影响存储器利用率和系统性能
存储器管理主要是内存管理,外存管理归入内存管理
4.1 存储器的层次结构
用户对存储器的要求:
- 速度快,与CPU相匹配
- 容量大
- 便宜
- 三个条件不能同时满足,全部采用层次结构存储器
4.1.1 多层结构的存储器系统
存储器的多层结构
通用计算机存储层次至少三级:R(寄存器),M(主存),S(辅存)
高档计算机更多层次:R ,高速缓存,M,磁盘缓存,固定磁盘,可移动存储介质
4.1.2 主存储器和寄存器
-
可执行存储器
寄存器和主存储器称为可执行存储器
- 其访问机制以及访问速度与辅存不同,辅存设及中断,设备驱动等,非常慢
- OS存储器管理负责可执行存储器的分配,回收,数据移动等管理
- OS的资源和文件管理负责对辅存的管理
-
主存储器
主存储器简称主存或内存
- 主存保存进程运行时的数据和数据,也称可执行存储器
- 程序执行时M和R互相传输数据,读/写
- 主存容量:B,KB,MB,GB
- 主存速度远低于cpu,因此引入R和cache
- 寄存器
寄存器与处理机速度相同
- 访问寄存器速度最快,能与cpu协调工作
- 价格昂贵,容量小,配备几十个-几百个
- R长度:8b,16b,32b
- 通用R和准用R
4.1.3 高速缓存和磁盘缓存
-
高速缓存(cache)
介于CPU和M之间
- 访问速度快于M
- 主要备份主存较常用到的数据,减少CPU访问M的次数,提高程序执行速度
- 容量大于寄存器,nKb,nMb
- 程序局部性原理(时间/空间)
- 时间局部性:访问某数据在不久又再次被访问
- 空间局部性:访问某数据,这个数据附近的数据在不久也会被访问 数组/链表
- 二级或者多级cache,I-cache(访问指令),D-cache(访问数据)
-
磁盘缓存
磁盘I/O速度远远低于主存访问速度
- 为缓和两者速度不匹配,设置磁盘缓存
- 暂时存放频繁使用的部分磁盘数据和信息,以减少访问次数
- 磁盘缓存不是一种实际存在的存储器
- 利用主存的部分存储空间暂时存放从磁盘中读到的I\O信息
- 数据在文件(磁盘)–磁盘缓存–主存—cache–R之间传输
4.2 程序的装入和链接
对用户程序处理步骤
编译:得到目标模块
链接:链接程序生产完整装入模块
装入:装入程序将模块装入内存
4.2.1 程序的装入
-
绝对装入方式
- 早期单道程序采用绝对装入方式,DOS
- 用户程序编译后产生绝对地址(即 物理地址)的目标代码
- 程序装入位置固定
- 程序相对地址(逻辑地址)与实际地址相同,无需重定位
地址确定方法
①程序员直接使用绝对地址。要求熟悉内存情况,程序修改时要改变所有地址
②程序员使用符号(变量)地址,编译时转为绝对地址
-
可重定位装入方式(静态重定位)
重定位:装入目标模块时,对其逻辑地址进行修改的过程
静态重定位:地址变换在装入时一次完成且以后不再改变的方式
-
绝对装入目标模块只能装入到内存事先指定的位置,只适用于单道环境
-
多道环境中目标模块起始地址都从0开始,其它地址都相对于起始地址计算
-
逻辑地址与物理地址不同,采用可重定位装入方式
-
根据模块装入内存的起始地址修改模块内其它逻辑地址
-
-
动态运行时装入方式
-
静态重定位,一旦程序装入内存,该程序不可在内存中移动
-
程序代码经常需要移动,例如对换
-
动态重定位-动态运行时装入:
①装入时逻辑地址不变,装入内存的模块全采用逻辑地址
②每次运行时地址才变换
③需要硬件重定位寄存器支持
④允许程序在内存中移动位置
-
4.2.2 程序的链接
将多个目标模块以及库函数装配成一个完整的装入模块
-
静态链接
-
事先链接,程序运行前链接
-
运行前将所有目标模块和库函数链接成一个装入模块
-
连接时要解决的问题
① 对相对地址的修改 ② 变换外部调用符号
-
静态链接生成完整装入模块,即可执行文件,以后不再打开,可直接装入内存运行
-
.lib,.a
-
-
装入时动态链接方式
- 目标模块在装入内存时采用边装入边链接方式
- 在装入目标模块时,若发生外部模块调用事件,由装入程序去找该外部目标模块,并将其装入内存,并修改模块内相对地址
优点:
①便于修改和更新,修改一个模块不影响其他模块
②便于实现目标模块共享,将一个目标模块链接到几个应用模块
-
运行时动态链接方式
-
静态链接和装入时动态链接方式效率低,浪费内存
-
运行时动态链接:对某些模块的推迟到调用时候才运行
-
执行过程中未调用模块不会链接,不会调入内存
优点:加快装入过程,节省内存
-
.dll,.so
-
4.3 连续分配存储管理方式
最早出现的分配方式,流行于1960-1980
为每个用户分配一个连续的内存空间,程序逻辑地址及物理地址相邻
4.3.1 单一连续分配
用于单道程序环境
- 内存分为系统区和用户区两部分
- 系统区(低址部分)给OS使用
- 用户区仅占一道用户程序,程序独占整个用户空间
- 早期CP/M,MS-DOS,RT11等,不设存储保护机制
4.3.2 固定分区分配
最早用于多道系统存储管理方式,如早期IBM360的MFT系统
-
用户空间划分为若干个固定大小区域,每个分区装入一道作业
-
分区划分办法:
- 分区大小相等。方便,实用,但缺乏灵活性
- 分区大小不等。根据用户需求划分,分配灵活
-
易造成存储空间浪费
固定分区分配例子
将分区按大小进行排队,并建立一张分区使用表,表项包括每个分区的起始地址
大小及状态)(是否已分配)
4.3.3 动态分区分配
-
根据进程实际需求动态分配内存
-
装入新作业时,按照一定的分配算法,从空闲分区表或空闲分区链中选除一分区分配,对系统性能影响很大
-
两个分配算法:
- 按顺序搜索动态分区分配
- 按索引搜索动态分区分配
空闲分区表:记录每个空闲分区情况,每个空闲分区有一个表目:(分区号,分区大小,分区始址,状态)
空闲分区链:每个空闲分区首部和尾部设置一个前向指针和后向指针。通过前后向链指针将所有空闲分区链接成一个双向链
动态分区内存分配
-
从空闲分区表(链)中分配
-
请求分区大小u.size,每个空闲分区大小m.size,最小内存碎片size
动态分区内存回收
- 释放内存时,根据回收区首址,从空闲区(表)找到插入点
-
回收区与插入点的前一空闲分区F1连接
-
回收区与插入点的后一空闲分区F2连接
-
回收区同时与插入点的钱、后两个分区邻接
-
回收区既不与F1邻接,又不与F2邻接,为回收区单独建立一个新表项
4.3.4 基于顺序搜索的动态分区分配算法
-
系统空闲分区构成一个链
-
依次搜索空闲分区链上的分区,直到找到大小满足的分区
顺序搜索分为4种
- 首次适应法
- 循环首次适应法
- 最佳适应法
- 最坏适应法
- 首次适应(FF)算法
-
空闲分区链以地址递增次序链接
-
从链首开始顺序查找,知道找到大小满足要求的一个空闲分区
-
从分区划分出空间分配,余下空闲分区仍留在空闲链中
-
若找不到,则内存分配失败
特点
①优先使用地址内存,保留高址内存空闲区
②容易产生碎片
③从链首查找,增加查找开销
- 循环首次适应(NF)算法
-
为避免地址部分留下很多小的空闲区,以及减少可空闲分区的开销
-
NF算法从上次找到的空闲分区的下个分区开始查找
-
应设置一个起始查找指针,采用循环查找法
特点
①碎片减少
②缩短查找时间
③缺乏大的空闲分区
- 最佳适应(BF)算法
- 总是分配满足要求且最小的空闲分区
- 要求空闲分区按容量从小到大排序
- 第一个找到的分区即是最佳
- 效果并非最佳,太多无用碎片
- 最坏适应(WF)算法
-
总是挑选最大的空闲区分配
-
要求空闲区按照从大到小排序
特点
①碎片少,对中小作业有利
②查找效率高
③缺乏大的空间分区
4.3.5 基于索引搜索的动态分区分配算法
-
基于顺序搜索的动态分区算法不适用于太大的的系统
大中型采用基于索引的动态分区算法,分三种:
-
快速适应算法
-
伙伴系统
-
哈希算法
-
1.快速适应算法
-
又称分类搜索法,将空间大小按容量大小分配
-
系统有多个空闲区链,每类相同容量分区单独设置一个分区链
-
内存中设立一张管理索引表,每个索引表项对应一个分区链,并记录分区链表头指针
-
按照进程常用空间大小进行空闲分区分类
分配方法
①找满足条件最小的分区链
②取第一块分配
优点
①不分割分区,无碎片并保留大分区
②查找效率高
缺点
①归还分区复杂,系统开销大
②以进程为单位,一个分区只属于一个进程,有浪费
- 伙伴系统
-
规定所有分区大小均为2的K次幂(I<K<m,总内存2m)
-
开始运行时整个内存是2m的一个空闲分区
-
相同大小空闲分区单独设置一个双向链表,共有k个空闲区
-
请求分配2i-1≤n≤2i,查找2i,2i+1…,分配时可能多次分割内存
-
内存回收时可能多次合并
分配方法
分配一个长度为n的的存储空间,计算一个i值,22-1<n<2i,在空闲分区为2i的空闲分区链表查找
若找到,则分配,反之从2i+1分区链表开始查找
若有 2i+1的空闲分区,则把该分区分为相同的两个分区,这就是伙伴,其中一个用于分配另外一个用于加入2i的空闲分区
若2i+1分区也不存在,则找2i+2分区,依次查找
特点
①分配回收时间性能比快速适应法差,比顺序搜索法好
②内存适用率比快速适应法好,比顺序搜索法差
③多处理机系统仍广泛适应
- 哈希算法
-
利用哈希犯法快速查找的优点,add=hash(key)
-
构造以空闲分区大小为关键字的哈希表,每个表项指向对应空闲分区链表
-
根据所需空闲分区大小,通过哈希函数计算,得到哈希表项位置,从中得到相应空闲分区链表,实现最佳分配
4.3.6 动态可重定位分区分配
紧凑
-
连续分配要求分配一片连续的内存空间
-
不能利用小的空闲分区称为碎片或零头
-
通过移动内存作业位置,把多个分散小空闲分区拼接大分区称为紧凑或拼接
-
每次紧凑后要程序重定位
动态重定位
-
动态运行时装入方式,在装入内存的所有地址仍是相对(逻辑)地址,运行时才转换为绝对(物理)地址
-
用硬件地址变换提高效率
-
增设重定位寄存器,存放程序(数据)在内存的起始地址
-
执行真正访问的内存地址是相对地址与重定位寄存器和
-
紧凑时只需要用新起始地址修改重地位寄存器
动态重定位分区算法
-
动态重定位分区算法和动态分区算法基本相同,只多了个"紧凑"
-
当找到足够大空闲分区时,若所有小空闲分区容量总满足要求,则进行紧凑
-
无法紧凑时分配失败
4.4 对换
又称交换技术
- 一次调入一个作业,其他对换到外存后备队列,要求外存速度够快,能容纳所有作业
4.4.1 多道程序环境下的对换技术
对换的引入
- 对换概念,为什么要对换
- 对换改善内存和cpu利用率,提高系统吞吐量
- 被广泛采用,linux有对换进程和swap分区,windows也支持对换功能
对换的类型
-
每次对换都是将一定量的程序或数据,从内存中换入和换出
-
根据每次对换时对换的数量分为两类
①整体对换
- 也叫进程对换,以进程为单位,解决内存紧张问题,广泛用于多道程序系统的中级调度。
②页面(分段)对换
- 也称为部分对换,以页面或分段为单位,目的支持VM,用于请求页面或请求分段存储管理中
4.4.2 对换的空间管理
对换空间管理的主要目标
-
具有对换功能的OS磁盘空间分为文件区和对换区两部分
①对文件区管理的主要目标
- 大部分磁盘空间,存放文件目录和内容,主要目标提高磁盘存储空间利用率,采用离散分配方式
②对对换空间管理的主要目标
- 存放换出的进程,主要目标提高对换速度,采用连续分配,较少考虑外存碎片
对换空间磁盘块管理的数据结构
-
为管理对换区的空闲盘块,应配置相应数据结构,记录外存对换区中空闲盘块使用情况
-
动态内存分区分配类似,采用空闲盘块表或空闲盘块链
-
空闲盘块表应包含两项:
①对换区地址,用盘块号表示
②对换区大小,用盘块数表示
对换空间的回收和利用
- 对换分区采用连续分配,其分配与回收与动态分区方式类似
- 分配算法可以是首次适应算法,循环首次适应算法和最佳适应算法
- 分配回收操作要根据前后对换分区使用情况进行分割或合并
4.4.3 进程的换出和换入
进程的换出
-
内核发现内存不足时唤醒对换进程执行换出
-
对换进程将内存中某些进程调出至对换区,腾出内存空间
-
换出过程可分为以下两步
-
选择被换出的进程:选择标准
①首先选出阻塞或睡眠状态进程想
②有多个时选择低优先级进程
③还要考虑进程在内存中驻留时间
④若无阻塞进程,则选低优先级进程
-
进程换出过程:只能换出非共享段
-
进程的换入
- 对换进程定时执行换入操作
- 找“就绪”状态已换出进程,有多个时选择换出时间最久的进程
- 对换很消耗时间,OS正常运行不启动对换进程,发现经常内存不足(例如:缺页(段)中断)时才对换
4.5 分页存储管理方式
-
离散式内存管理
连续内存分配有碎片,紧凑开销大
离散内存分配允许将进程分散装入许多不相邻的内存空间
① 分页存储管理方式
② 分段存储管理方式
③ 段页式存储管理方式
4.5.1 分页存储管理的基本方法
-
分页管理的页面物理块
- 逻辑地址空间分为若干页,物理地址分为若干块,都从0编号
- 逻辑页大小=物理块大小
- 以块为单位进行分配,进程逻辑页装入不邻接多个物理块
- 页太小:减少页内碎片,但页表长,占内存,影响换入换出效率
- 页太大: 页表段,提高换入换出,页内碎片增大
-
分页管理的地址结构
分页系统的逻辑地址结构:
- 位移量即页内地址
若页面大小为L,逻辑地址为A,则页号P和页内地址d为:
-
页表
-
分页系统允许将进程各个逻辑页离散的存储在内存任意地址块
-
为每个进程建立一个映像表,简称页表
-
页表的作用:实现逻辑地址和物理块号的映射
-
进程每个逻辑页占一个表项
-
页表项内容:逻辑页号,物理块号,存储控制字段
- 页表实例:
-
4.5.2 地址的变换机构
(一般通过硬件实现)地址变换机构作用:实现逻辑地址到物理地址的转换
-
由于页内地址和物理块内地址对应,地址变换主要是逻辑页号到物理块号的变换
-
地址变换借助页表实现
-
地址变换频繁发生,用硬件实现
页表用寄存器实现&页表驻留内存
系统设置一个页面寄存器PTR,存放页表首及页表长度
页表首址及页表长度存于进程PCB,运行时装入PTR
分页系统地址变换过程
具有快表的地址变换机构
-
基本分页系统存取一个数据要两次访问内存
-
快表,联想寄存器或TLB,具有并行查找能力的特殊高速缓冲存储器
-
快表用于缓存页表中经常访问的页表项
-
程序局部性原理
-
命中率高的快表约损失10%的速度
-
快表分页系统地址变换过程
4.5.3 访问内存的有效时间EAT
从发出逻辑地址访问请求到访问实际物理地址单元并取出数据所花费的时间
设t为一次访问内存的有效时间,则:
①基本分页系统:EAT=2t
②具有快表的分页系统:EAT= a×λ+(t+λ)(1-a)+t=2t+λ-t×a
λ为查找快表时间,a为命中率
页表占用空间内存问题
OS逻辑空间很大,页表占用很大的连续内存空间
例如:32位逻辑地址,4kb页大小,1M个表项
- 解决办法:
- 页表采用离散内存分配
- 部分页表调入内存,其他在磁盘,需要时调入
4.5.4 两级和多级页表
两级页表
- 解决难找到大连续内存空间存放表,但页表占空间问题未解决
- 将内页表分页为页表再建立一张页表(外层页表),该页表项记录页内表的内存首地址
- 逻辑地址:外层地址、外层页内地址、页内地址
- 两级页表地址变换示例
- 增加一个外层页表寄存器,存放外层页表始址
多级页表
-
对于32位及其两级页表是合适的
-
对于64位需采用多级页表
多级页表是把两级页表再分页,并装入不同物理空间
目前64位OS逻辑地址空间最大为64TB=264,三级页表可行
4.5.5 反置页表
-
逻辑空间大,页表项很多
-
为减少页表占用空间,引入反置页表,也称倒排页表
普通页表
每个进程一个页表,每个逻辑页一项,存放物联块号
反置页表
整个系统一个页表,每个物理块设置一个表项,并按物理块号排序,内容为进程标识及其逻辑页号
反置页表的地址变换
①根据进程标识和页号,去检索反置页表
②若检索到,用物理块号和页内地址访问数据
③反之,则此页未装入内存,产生缺页中断再调入或者报错
特点
①减少页表占用内存
②每个进程还需要一个外部页表,记录各页在外存中的地址
③检索反置页表浪费时间,可以hash解决,会出现hash冲突
4.6 分段存储管理方式
存储器管理的发展
- 以提高内存利用率为目的:
- 连续分配:单一连续分配–>固定分区分配–>动态分区分配
- 连续分配–>页式分配
- 以满足用户和程序员编程需要
- 自然划分、共享、保护、动态链接、动态增长
4.6.1 分段存储管理方式的引入
为什么需要分段存储管理?
-
分段存储管理更好符合程序员如下需求:
① 方便编程
- 用户程序按照逻辑关系划分为很多个段,每个段都是从0号开始编址,并有自己的名称和长度,程序逻辑地址由(段名)段号,段内偏移量(段内地址)组成,方便编程,程序非常直观,可读性好
② 信息共享
- 共享过程,函数为单位,段是信息逻辑单位,用页划分不合理
③ 信息保护
- 信息保护也是以过程、函数为单位
④ 动态增长
- 数据段动态内存分配,很难进行预分配
⑤ 动态链接
- 动态链接要以目标程序(即段)为单位
4.6.2 分段系统的基本原理
分段式存储管理方式
-
用户地址空间分为若干个段,每个段定义一组逻辑信息
-
每个段都有名字和长度,都从0号开始编址,采用连续分配
-
程序地址空间分为多个段,各段长度不同,程序逻辑地址由段名(段号)和段内偏移量(段内地址)组成
-
分段 地址中地址具有如下结构:
段表
-
分段式存储管理中,每段分配一个连续分区
-
一个进程有多个段,各段离散的装入内存不同分区中
-
每个进程一张段映射表(段表),每个段占一项,记录该段在内存首地址和段长
-
段表放于内存(或R中),用于实现地址转换
段式存储地址变换机构
-
系统设置一个段表寄存器,用于存放段表始址和段表长度
-
一次访问数据需两次访问内存
-
可用快表来保存常用段信息
-
进程段数远远少于页数
分段和分页区别
分页 | 分段 |
---|---|
页是信息物理单位,用户不可见 | 段是信息逻辑单位,用户可见 |
分页目的是提高内存利用率 | 分段目的是满足用户需求 |
页的大小是固定且由系统决定 | 段长度不固定,由用户程序决定 |
分页是一维地址空间 | 分段式一维逻辑空间 |
4.6.3 信息共享
分页系统信息共享
-
分段系统可方便段的共享和保护
-
分页系统也可以实现程序和数据共享,但不如分段系统方便
-
分页系统要求各进程页表中共享代码的页表项指向同一物理块
-
分页系统信息共享示例
分段系统信息共享
-
分段系统中共享段只有一个段表项,共享非常容易
4.6.4 段页式存储管理方式
- 分页系统以页为单位,减少碎片,提高内存利用率
- 分段系统以段为单位,更好满足用户需求
- 段页式系统将两者结合,既能减少外碎片,又能分别共享保护可动态链接
段页式存储管理基本原理
- 将分页分段结合,先将用户程序分成若干段,每段分成若干页
- 地址结构由段号,段内页号,页内地址三部分组成
- 一个进程有一张段表和多张页表,段表项分为页表始址和页表长度
地址空间和地址结构示例
管理段表页表示例
段页式地址变换
- 段页式系统配置一个段表寄存器,存放段表始址和段长
- 一次访问数据需三次访问内存,可用快表提高转换速度
段页式地址变换图示
- 参考:计算机操作系统(第四版)(汤小丹)