存储器的层次结构
存储层次
➢ CPU寄存器
➢ 主存:高速缓存、主存储器、磁盘缓存
➢ 辅存:固定磁盘、可移动介质
层次越高,访问速度越快,价格也越高,存储容量也最小
寄存器和主存掉电后存储的信息不再存在(易失性存储器)
辅存的信息长期保存(非易失性存储器)
可执行存储器:寄存器和主存储器。
主存储器:内存或主存。
寄存器:访问速度最快,与CPU协调工作,价格贵。
高速缓存:介于寄存器和存储器之间。
磁盘缓存
➢暂时存放频繁使用的一部分磁盘数据和信息;
➢缓和主存和I/O设备在速度上的不匹配;
➢利用主存的部分空间,主存可看成辅存的高速缓存。
内存又分为ROM和RAM,ROM为固化只读的。因此操作系统的存储管理模块管理的是内存中的RAM
内存可以看作是以字或字节为单位的存储单元组成的数组,每个存储单元都有自己的地址
内存的作用:存储指令和数据。程序执行时,先加载到内存。CPU执行时,从内存取指令,分析指令,如需要则从内存取操作数。执行完毕后,存储运算结果到内存
1. 内存分配和回收:为每个进程分配内存空间,并在它们不需要时回收其占据的空间。方式:①静态分配:作业运行前一次性完成;②动态分配:作业运行前和运行中逐步完成
2. 内存保护:为防止内存中程序相互干扰,要设置地址空间访问权限(读、写、执行)和越界检查机制。
3. 地址映射:将地址空间中的逻辑地址转化为内存空间中与之对应的物理地址。
4. 内存扩充(逻辑扩充):即在不改变实际内存容量情况下,借助大容量外存解决内存不足问题。
地址的概念
1. 物理地址(内存地址,绝对地址,实地址,physical address):把内存分成若干个大小相等的存储单元,每个单元给一个编号,这个编号称为物理地址。物理地址可直接寻址。
物理地址空间:物理地址的集合称为物理地址空间(内存空间),它是一个一维的线性空间。
2. 逻辑地址(相对地址,虚地址,logical address):一个源程序经编译、链接而形成可装入程序,其地址是从“0”开始的,程序中的其它地址都是相对于起始地址计算的,故称相对地址。
逻辑地址空间:由逻辑地址所形成的地址范围。可能是线性的,也可能是多维的。
1. 地址映射(address mapping):将用户程序中的逻辑地址转换为运行时由机器直接寻址的物理地址。有时也称为地址变换、地址重定位。
2. 当程序装入内存时,操作系统要为该程序分配一个合适的内存空间,由于程序的逻辑地址与分配到内存物理地址不一致,而CPU执行指令时,是按物理地址进行的,所以要进行地址转换。
程序的装入和链接
程序的运行步骤
编译:由编译程序(Compiler)对源程序进行编译,形成若干个目标模块
链接:由链接程序(Linker)将目标模块和它们所需要的库函数链接在一 起,形成一个完整的装入模块(Load Module)
装入:由装入程序(Loader)将装入模块装入内存
物理地址(绝对地址)
➢ 物理内存的地址,内存以字节为单位编址
➢ 物理地址空间:所有物理地址的集合
逻辑地址(虚拟地址、相对地址)
➢ 由CPU产生的地址,即程序编译后使用的相对于0字节的地址
➢ 逻辑地址空间:由程序所生成的所有逻辑地址的集合
内存保护的实现:硬件
➢ 基地址寄存器:保存最小的合法物理内存地址(基地址)
➢ 界限寄存器:保存合法的地址范围大小(界限地址)
➢ 内存空间保护的实现
⚫ 判断“基地址≤物理地址<(基地址+界限地址)”是否成立。
程序的装入
绝对装入方式
➢ 编译时产生的地址使用绝对地址
➢ 程序或数据被修改时,需要重新编译程序
可重定位装入方式
➢ 编译后的目标模块使用相对地址
➢ 在装入时,完成重定位(静态重定位)
➢ 不需硬件支持
动态运行时装入方式
➢ 编译后的目标模块使用相对地址
➢ 在运行时,完成重定位(动态重定位)
1. 绝对装入(absolute loading)
单道程序中,由编译程序或程序员指定内存地址,装入时直接定位在上述(即文件中记录的地址)内存地址。逻辑地址和物理地址完全相同。(单一装入模块装入)
2. 优点:装入过程简单,实现容易
3. 缺点:需要有连续的空间,不适于多道程序系统
1. 可重定位装入(relocation loading)
多道程序环境中,单一装入模块中采用逻辑地址,根据当前内存情况,将装入模块装入到适当位置。操作系统装入模块进行地址映射。地址映射(地址转换)是在装入模块装入内存时一次性进行的,即采用静态重定位。以后不能更改
2. 优点:不需硬件支持,可以装入有限多道程序
3. 缺点:程序装入内存后不能移动,不易实现共享
动态运行时装入(dynamic run-time loading)
在运行过程中,程序在内存中的位置可能经常要改变!
将装入模块原样装入内存,而地址映射工作推迟到程序真正执行时才进行,即采用动态重定位。
⚫ 动态重定位:地址变换过程是在程序执行期间,随着对每条指令和数据的访问而自动进行的。
⚫ 重定位寄存器:须获得硬件地址变换机构的支持。
⚫ 程序移动特点:允许程序在运行期间在内存中移动
⚫ 优点:
– OS可以将一个程序分散存放于不连续的内存空间,可以移动程序,有利用实现共享。
– 能够支持程序执行中产生的地址引用,如指针变量(而不仅是生成可执行文件时的地址引用)。
⚫ 缺点:需要硬件支持,OS实现较复杂。
程序的链接
静态链接
➢ 在程序运行前,将各目标模块及它们所需的库函数链接成一个完整的装配模块,以后不再拆开
➢ 对相对地址进行修改;变换外部调用符号
链接时间:
静态链接是在生成可执行文件时进行的。
链接地址类型:
在目标模块中记录符号地址(symbolic address),而在可执行文件中改写为指令直接使用的逻辑地址。
装入时动态链接
➢ 在装入内存时,采用边装入边链接的链接方式
➢ 便于修改和更新
➢ 便于实现对目标模块的共享
1. 链接对象:程序由多个文件(模块)组成,在装入或运行时临时进行链接。通常被链接的共享代码称为动态链接库(DLL, DynamicLink Library)或共享库(shared library)
2. 时间:根据链接发生时机的不同,又分为了装入时链接(Loadtime Dynamic Linking)和运行时动态链接(Run-time Dynamic Linking)
3. 优点:由于运行时动态链接具有更高的灵活、有效性,所以成为目前流行的方式
运行时动态链接
➢ 将某些目标模块的链接推迟到执行时才执行。即在执行过程中,若发现一个被调用模块尚未装入内存时,立即由OS去找到该模块并将它装入内存,并把它链接到调用者模块上
➢ 加快装入过程,节省大量的内存空间
对换:把内存中暂时不能运行的进程或者暂时不用的程序和数据,调出到外存上,以便腾出足够的内存空间,再把已具备运行条件的进程或进程所需的程序或数据,调入内存。
整体对换:对换以整个进程为单位,也称为进程对换
➢ 被广泛应用于多道程序系统,也称为处理机中级调度
页面(分段)对换:对换是以“页”或“段”为单位进行的,又统称为“部分对换”
➢ 目的是为了支持虚拟存储系统
为了实现进程对换,系统必须能实现三方面的功能
➢ 对换空间的管理
➢ 进程的换出
➢ 进程的换入
覆盖
1 解决问题→程序大小超过物理内存总和
2 程序执行时:
➢ 只在内存中保留那些在任何时间都需要的指令和数据;
➢ 程序的不同部分在内存中相互替换。
3由程序员声明覆盖结构,不需要操作系统的特别支持
4覆盖结构的程序设计很复杂
5应用于早期的操作系统
连续分配方式(简称:连续分配):是指为一个用户程序分配空间的时候,将所有程序装入到一段连续的物理内存中。在早期(20世纪60-70年代)的操作系统中,这种分配内存的方式曾经被广泛的使用。
单一连续分配
固定分区分配
固定分区主存利用率不高,使用不灵活,所以出现了可变分区
1. 改变“呆板”的分区固定为对进程特性的自适应
2. 按进程的大小动态划分分区大小(分区大小、数目可变)
空闲分区表
–每个空闲分区占用一个表项
–分区表的表项中包含分区号、分区始址及分区大小等表目
–表长不易确定
–占用额外内存
空闲分区链表
–利用各空闲分区自身的单元组成双向链表
–操作速度较慢
–克服了空闲分区表(表长不确定)的缺点
分区分配操作-内存回收
1. 合并:当一个进程(或程序)释放其所占内存区时,系统将首先检查回收区是否与其它空闲区相邻,若相邻则合并成一个空闲区,否则,将回收区插入空闲分区表(或空闲分区链)中的适当位置
2. 回收情况:
A. 只有前邻空闲区
B. 只有后邻空闲区
C. 既有前邻空闲区又有后邻空闲区
D. 没有邻接空闲区
根据不同情况,A、B、C有不同的合并策略
➢ 顺序搜索:依次搜索空闲分区链上的空闲分区,去找满足需要的空闲分区
➢ 常用到的分配算法有:
⚫ 首次适应算法(first-fit)
⚫ 下次适应算法(next-fit) 即循环首次适应法
⚫ 最佳适应算法(best-fit)
⚫ 最坏适应算法(worst-fit)
为提高空闲分区搜索速度,大中型系统往往采用基于索引搜索的动态分区分配算法:
1. 快速适应算法
2. 伙伴系统
3. 哈希算法
快速适应算法
1. 别名:分类搜索法
2. 按容量大小进行分类。将空闲分区按容量大小进行分类,每一类具有相同容量,每一类单独设立一个空闲分区链表(空闲分区的分类根据进程常用的空间大小进行划分)
3. 多个空闲分区链表。系统有多个空闲分区链表
4. 管理索引表。在内存中设立一张管理索引表,每个表项对应一类空闲分区,并记录该类空闲分区链表表头指针
优点:查找效率高;空闲分区分配时,不产生分割,能保留大分区,也不产生内存碎片
缺点:为有效合并分区,分区归还主存算法复杂,系统开销大;分配分区以进程为单位,存在浪费;以空间换取时间
伙伴系统
1. 固定分区限制了活动进程的数目,当进程大小与空闲分区大小不匹配时,内存空间利用率很低
2. 动态分区算法复杂,回收空闲分区系统开销大
3. 伙伴系统是一种折衷:
➢ 分区大小为2的k次幂,k为整数,1<=k<=m,2m是整个可分配内存的大小
➢ 将空闲分区按大小进行分类,每一类单独设立一个空闲分区双向链表
➢ 性能:分配和回收的性能取决于查找空闲分区的位置和分割、合并空闲分区的时间
➢ 时间性能:时间性能比分类搜索算法差,比顺序搜索算法好
➢ 空间性能:空间性能远优于分类搜索算法,但比顺序搜索算法略差
➢ 主要用于多处理机系统中(Linux早期版本)
连续分配方式存在的问题
➢ 碎片:不能被利用的小分区
➢ 解决方案:紧凑,要求代码和数据可以在内存中移动
➢ 紧凑:通过移动内存中的作业位置,以把原来多个分散的小分区拼接成一个大分区的方法,也叫“拼接”
动态重定位:在指令运行时,实现地址转换(相对地址转换为绝对地址)
分配算法:类似于动态分区分配算法,增加了紧凑的功能
1. 零头问题:可变式分区也有零头问题。在系统不断地分配和回收中,必定会出现一些不连续的小的空闲区,称为外零头。虽然可能所有零头的总和超过某一个作业的要求,但是由于不连续而无法分配
2. 拼接:解决零头的方法是拼接(或称紧凑),即向一个方向(例如向低地址端)移动已分配的作业,使那些零散的小空闲区在另一方向连成一片
3. 时间开销:分区的拼接技术,一方面是要求能够对作业进行重定位,另一方面系统在拼接时要耗费较多的时间
动态可重定位分区分配
1. 需硬件(重定位寄存器R)支持 ,该R中放程序在内存始址。
执行时,访问的内存地址是相对地址与重定位寄存器中的地址相加而形成的
2. 地址变换过程是在程序执行期间,随着对每条指令和数据的访问而自动进行的,故称动态重定位
3. 进行“紧凑”处理时,不需对程序进行改动,只要修改重定位寄存器的值,即程序在内存中新的起始地址就可以
动态重定位示意图
分区的存储保护:采用保护键
按块分配,一个作业各块相连,并给该作业分配一个键号,填入该作业的各块的保护键中(这个保护键相当于锁);并把该键号置入PSW的保护键字段(相当于钥匙)。当程序执行时,如所访问的保护键与钥匙不匹配,则产生保护键违例中断