1 存储系统的层次结构
寄存器:寄存器访问速度最快,完全能与 CPU 协调工作。寄存器的长度一般以字(word)为单位。
主存:CPU的控制部件只能从主存储器中取得指令和数据,数据能够从主存储器读取并将它们装入到寄存器中,或者从寄存器存入到主存储器。CPU 与外围设备交换的信息一般也依托于主存储器地址空间。由于主存储器的访问速度远低于 CPU 执行指令的速度,为缓和这一矛盾,在计算机系统中引入了寄存器和高速缓存。
高速缓存:主存中一些经常访问的信息存放在高速缓存中,减少访问主存储器的次数,可大幅度提高程序执行速度。当 CPU 访问一组特定信息时,首先检查它是否在高速缓存中,如果已存在,可直接从中取出使用,以避免访问主存,否则,再从主存中读出信息。
磁盘缓存:将频繁使用的一部分磁盘数据和信息,暂时存放在磁盘缓存中,可减少访问磁盘的次数。磁盘缓存利用主存中的存储空间,来暂存从磁盘中读出(或写入)的信息。
2. 程序的执行过程
1. 编译程序:
由程序源码 -> 目标模块。
2. 链接:
目标模块 + 库函数 -> 完整的装入模块。
静态链接
执行前进行,要做好
1. 相对地址转换:在由编译程序所产生的所有目标模块中,使用的都是相对地址,其起始地址都为 0,每个模块中的地址都是相对于起始地址计算的。
2. 变换外部调用标号:将每个模块中所用的外部调用符号也都变换为相对地址
装入时动态链接
用户源程序经编译后所得的目标模块,是在装入内存时边装入边链接的,即在装入一个目标模块时,若发生一个外部模块调用事件,将引起装入程序去找出相应的外部目标模块,并将它装入内存。
优点:1便于修改和更新2便于实现对目标模块的共享
运行时动态链接
在执行过程中,当发现一个被调用模块尚未装入内存时,立即由 OS 去找到该模块并将之装入内存,把它链接到调用者模块上。凡在执行过程中未被用到的目标模块,都不会被调入内存和被链接到装入模块上,
3. 装入(加载)程序
加载器把加载的模块放在内存中。
1. 绝对加载方式:
要求加载模块总被加载到内存的同一位置,
逻辑地址与实际地址相同,
要求程序员熟悉内存使用情况。
2. 可重定位装入方式(静态)
目标模块从0开始编址,其他地址相对于起始地址计算。
3. 动态运行装入
在程序执行时将相对地址转换为绝对地址,允许程序在内存中移动。
重定位
需硬件支持,基址寄存器内存放程序在内存中的起始地址,界限寄存器存放程序的终止位置。
执行过程为:首先基址寄存器中的值加上相对地址产生一个绝对地址;然后将此与界限寄存器的值比较,如果这个地址在界限范围内则继续该指令的执行;否则向系统发送中断信号。
Tips
内存空间(物理空间,绝对空间):由内存一系列存储单元所限定的地址范围
逻辑地址空间(地址空间):由程序中逻辑地址组成的地址范围
绝对地址(物理地址):内存中各物理存储单元的地址统一的基地址顺序编制,这种地址叫绝对地址。
相对地址(逻辑地址):用户程序经编译后的每个目标文件模块都以0为基地址顺序编制,这种地址叫相对地址。
可重入代码:一种允许多个进程同时访问但不允许任何进程修改的代码,又叫纯代码。
3. 内存的连续分配方式
单一连续分配
内存分为系统区和用户区;
在内存中只驻留一道程序,整个用户区被一个用户独占;
仅能用于单用户单任务的操作系统,如MS-DOS,CP/L。
–
固定分区分配
最简单的多道程序存储管理方式典型使用固定分区的是OS/MFT系统。但目前几乎没有操作系统使用;
将内存分为几个固定大小的区域,每个区域装入一道作业(划分分区的方法有1分区大小相等,不够灵活;2分区大小不等);
将分区按大小进行分配,建立分区使用表(分区起始地址,大小,状态)。
动态分区分配
数据结构
空闲分区表:每个分区占一个表目,包含分区序号,分区始址,分区大小。
空闲分区链:在每个分区的起始部分设置用于控制分区信息,向前指针,分区尾部设置一个向后指针,形成双向链表。
分区分配算法
1. 首次适应算法 FF
空闲分区链/表以地址递增的次序链接;
分配时从内存的小地址开始查找,找到一个满足要的空闲分区,从该分区划出一块内存给请求者,余下的仍留在空闲链中。
2. 循环首次适应算法(下次适配算法)
每次从上次找到的下一个分区开始查找(使空闲分区变得均匀,但会缺乏大的空闲分区)。
3. 最佳适应算法
将所有的空闲分区按容量以从小到大的顺序形成空闲分区链,第一次找到的空闲区肯定是最佳的。
4. 最坏适应算法
总是找最大的空闲分区分割作业使用。
5. 快速适应算法
又称为分类搜索法,是将空闲分区根据其容量大小进行分类,对于每一类具有相同容量的所有空闲分区,单独设立一个空闲分区链表。
分区分配操作(分配与回收)
分配 u.size 请求分区大小
m.size 空闲分区大小
不可再切割的剩余分区 size
进程运行完毕释放内存。
动态重定位分区分配
动态重定位:
地址变换过程使在程序执行期间,随着对每条指令或数据的访问自动进行,所以交动态重定位。要求有重定位寄存器的硬件支持(静态重定位把相对地址转换为绝对地址,发生在装入之前,不需要硬件支持)。
碎片 内存中不能被利用的小分区
紧凑/拼接 分散的小分区拼接成为一个大的分区
对换
把内存中暂时不用的程序或数据调到外存,把已经具备条件的调入内存。(中级调度)
对换实现的功能
1. 对换空间的管理 外存的空间分为比较稳定的,离散分配的文件区和连续分配的对换区。
2. 进程的换出
--找出内存中处于阻塞状态且优先级最低的进程;
--启动盘块,将该进程的程序和数据传到磁盘上的对换区;
--若没出错,就回收该进程所占的内存空间,修改进程PCB。
3. 进程的换入
--系统定时查看所有进程的状态;
--找出外存就绪但是已经换出的进程;
--将其中换出时间最久的进程换入;
--直到没有可以换入的进程或者没有可换出的进程为止。
4. 基本分页式
1. 不具备分页对换功能,不支持虚拟存储器功能,又叫纯分页存储管理方式。
2. 将进程的逻辑地址空间分为若干大小相等的片,叫做页面,并为各页编号。
3. 把内存空间分成与内存页面相同大小的若干存储块,叫做块或页框,页进行编号。
4. 以块为单位将进程中的若干页分别装入多个可以不相邻的物理块中。
页内碎片进程的最后一页经常不满一块而形成的不可利用的碎片。
页面大小1 通常512B-8KB。页面太小,提高内存利用率,但页表过长占内存,降低对换效率;页面太大,提高兑换速率,降低内存利用率。
页表:系统为了在内存中找到每个页面对应的物理快为进程而建立的页面映射表。其作用是实现从页号到物理块号的地址映射。
1. 页表由一组专门的寄存器实现,一个页表项用一个寄存器;
2. 页表大多数驻留在内存;
3. 系统只设置一个页表寄存器PTR,存放页表在内存的值值和页表长度;
4. 进程未执行时页表的始值和页表长度存放在本进程PCB中,当调度到进程时装入页表寄存器。
地址变换
基本任务
实现从逻辑地址到物理地址的转换(将逻辑地址中的页号转换为内存中的物理块号),需借助页表(是硬件)完成。
步骤
1. 拿出页号
2. 页表长度大于等于页号正常,否则就是溢出
3. 页表首地址+页号=块号
Tips
· 2次访问内存:1访问页表;2找到指定页的物理块号,+页内偏移量拼接成物理地址,据此访问内存的数据。
· 引入快表后的有效访问时间 T = (命中率h * 两次访问时间t1) +(1-命中率h) * 三次访问时间t2)
两级列表
原因
随着逻辑地址空间的增多,页表越来越大,占用内存空间变多。
解决
1. 采用离散分配方式来解决难以找到一块连续的大内存空间的问题;
2. 只将当前需要的部分页表项调入内存,其余的页表项仍驻留在磁盘上,需要时再调入。
说明对于要求连续的内存空间来存放页表的问题,可利用将页表进行分页,并离散地将各个页面分别存放在不同的物理块中的办法来加以解决,同样也要为离散分配的页表再建立一张页表,称为外层页表(Outer Page Table),在每个页表项中记录了页表页面的物理块号。
5. 基本分段方式
分段的引入
主要是为了满足用户(程序员)在编程和使用上多方面的要求,1方便编程;2信息共享;3信息保护;4动态增长;5动态链接。
基本原理
作业的地址空间被划分为若干个段,每个段定义为一组逻辑信息;
每个段都从0开始编址,采用一段连续的地址空间,短的长度由相应的逻辑信息组的长度决定,因而段长不等;
整个作业的地址空间分为多少段是二维的(段与段之间没有联系,页与页之间有编号所以是一维的)。
段表
系统给每个进程建立一个段映射表,用于实现从逻辑段到物理内存的映射。
分页与分段的区别
1. 页是信息的物理单位,分页是由于系统管理的需要
段是信息的逻辑单位,分段为满足用户()程序员的需要
2. 页的大小固定,由系统决定
段的长度不固定,由用户的程序决定(通常实在编译时根据信息性质划分)
3. 分页的作业是一维的,程序员只需要利用一个及富,就可以表示一个地址;
分段作业时二维的,程序员标识一个地址时既需要给粗段名有需要给出段内地址值。
地址变换
1. 在系统中设置了段表寄存器,用于存放段表始址和段表长度 TL。在进行地址变换时,系统将逻辑地址中的段号与段表长度TL 进行比较。若 S>TL,表示段号太大,是访问越界,于是产生越界中断信号;
2. 若未越界,则根据段表的始址和该段的段号,计算出该段对应段表项的位置,从中读出该段在内存的起始地址;
3. 然后,再检查段内地址 d 是否超过该段的段长 SL。若超过,即 d>SL,同样发出越界中断信号;
4. 若未越界,则将该段的基址 d 与段内地址相加,即可得到要访问的内存物理地址。
段页式存储
1. 既由分段系统的便于实现,分段可共享,易于保护,可动态链接的优点。
2. 又可以像分页那样解决内存的外部碎片问题,以及可以为各个分段离散地分配内存的问题。
基本原理
1. 分段和分页原理结合;
2. 先将用户程序分成若干段;
3. 把每个段分成若干个页,并把每个段给一个段名。
三次访问内存
1. 访问段表
2. 访问页表
3. 真正访问指令或数据
.
.
.
.
.
.
桃花仙人种桃树,又摘桃花换酒钱_