1.58k likes | 1.79k Views
Chapter4 存储器管理. § 4.1 程序的装入和链接. § 4.2 连续分配方式. § 4.3 基本分页存储管理方式. § 4.4 基本分段存储管理方式. § 4.5 虚拟存储器. Cache. 主 存. 磁 盘. §4.1 概 述. 高速缓存 Cache : 少量的、非常快速、昂贵、易变的 内存 RAM : 若干兆字节、中等速度、中等价格、易变的 磁盘: 数百兆或数千兆字节、低速、价廉、不易变的. 存储器的层次结构. 位于 RAM 中的 操作系统 用户程序. 内 存.
E N D
Chapter4存储器管理 §4.1程序的装入和链接 §4.2连续分配方式 §4.3基本分页存储管理方式 §4.4基本分段存储管理方式 §4.5虚拟存储器
Cache 主 存 磁 盘 §4.1概 述 高速缓存Cache: 少量的、非常快速、昂贵、易变的 内存RAM: 若干兆字节、中等速度、中等价格、易变的 磁盘: 数百兆或数千兆字节、低速、价廉、不易变的 存储器的层次结构
位于RAM中的 操作系统 用户程序 内 存 由存储单元(字节或字)组成的一维连续的地址空间,简称内存空间。用来存放当前正在运行程序的代码及数据,是程序中指令本身地址所指的、亦即程序计数器所指的存储器. 分为: • 系统区:用于存放操作系统 • 用户区:用于装入并存放用户程序和数据 0
§4.1.1OS对存储器的管理 • 由操作系统协调这些存储器的使用 • 重要性: 直接存取要求内存速度尽量快到与CPU取指速度相匹配,大到能装下当前运行的程序与数据,否则CPU执行速度就会受到内存速度和容量的影响而得不到充分发挥
存储管理的目的 • 充分利用内存,为多道程序并发执行提供存储基础 • 尽可能方便用户使用 自动装入用户程序 用户程序中不必考虑硬件细节 • 系统能够解决程序空间比实际内存空间大的问题
存储管理的目的(续) • 程序在执行时可以动态伸缩 • 内存存取速度快 • 存储保护与安全 • 共享与通信 • 了解有关资源的使用状况 • 实现的性能和代价
存储管理的任务 • 存储分配 • 这是存储管理要研究的主要内容。 • 地址映射 • 研究各种地址变换机构,以及静态和动态重定位方法。 • 存储保护 • 研究如何确保每道程序都在自己的内存空间运行,互不干扰(防止地址越界);研究如何保护各程序区中的信息不被破坏和偷窃(防止操作越权)。 • 内存扩充 • 内存扩充研究如何从逻辑上扩充内存,而不是从物理上扩充内存。
§4.1.2存储管理的分类 • 连续分配方式 • 离散分配方式 • 虚拟存储管理系统
连续分配方式 • 连续分配方式是指系统为一个用户程序分配一个连续的存储空间。这种分配方式曾被广泛应用于20世纪60-70年代的操作系统中. • 单一连续分配方式。 将内存划分成系统区和用户区两个分区,用户区仅被一个用户所独占。例如,MS DOS。 • 分区式分配方式。 • 固定分区式 将内存的用户区预先划分成若干个固定大小的区域,每个区域中驻留一道程序 • 可变分区式 每个分区的大小不固定,分区数目也不固定
离散分配方式 • 为进一步提高内存的利用率,引入了离散分配方式。它将一个用户程序离散地分配到内存中的多个互不邻接的区域。离散分配方式有以下三种: • 分页存储管理方式 • 分段存储管理方式 • 段页式存储管理方式
虚拟存储管理方式 • 为进一步提高内存的利用率,实现从逻辑上扩充内存的功能,引入了虚拟存储管理系统。虚拟存储管理系统有三种: • 请求分页系统 • 请求分段系统 • 请求段页系统
§4.1.3程序的装入和链接 定义 • 可重定位(Relocatable) 程序的镜像可以驻留在物理内存的任何位置 • 绑定(Binding) – 程序驻留在内存的什么位置? • 逻辑地址到物理地址的映射(Mapping) • 映射工作在编译/链接(compile/link) 期间完成 • 编译(Compile) 把一种(程序)翻译成机器语言 • 装载(Load) 找到最佳的位置,将可重定位的代码Binding到物理内存
程序的装入和链接(续1) • 在多道程序环境下,要使程序运行,必须先为之创建进程。 • 将一个用户源程序变为一个可在内存中执行的程序,通常都要经过以下几个步骤: • 首先是要编译,由编译程序将用户源代码编译成若干个目标模块; • 其次是链接,由链接程序将编译后形成的一组目标模块,以及它们所需要的库函数链接在一起,形成一个完整的装入模块; • 最后是装入,由装入程序将装入模块装入内存。
程序的装入和链接(续2) 4 void main() 5 { 6 printf( "Hello, from main\n" ); 7 b(); 8 } 9 10 11 void b() 12 { 13 printf( "Hello, from 'b'\n" ); 14 } Binding Logical To Physical
程序的装入和链接(续3) ASSEMBLY LANGUAGE LISTING 000000B0: 6BC23FD9 stw %r2,-20(%sp ; main() 000000B4 37DE0080 ldo 64(%sp),%sp 000000B8 E8200000 bl 0x000000C0,%r1 ; get current addr=BC 000000BC D4201C1E depi 0,31,2,%r1 000000C0 34213E81 ldo -192(%r1),%r1 ; get code start area 000000C4 E8400028 bl 0x000000E0,%r2 ; call printf 000000C8 B43A0040 addi 32,%r1,%r26 ; calc. String loc. 000000CC E8400040 bl 0x000000F4,%r2 ; call b 000000D0 6BC23FD9 stw %r2,-20(%sp) ; store return addr 000000D4 4BC23F59 ldw -84(%sp),%r2 000000D8 E840C000 bv %r0(%r2) ; return from main 000000DC 37DE3F81 ldo -64(%sp),%sp STUB(S) FROM LINE 6 000000E0: E8200000 bl 0x000000E8,%r1 000000E4 28200000 addil L%0,%r1 000000E8: E020E002 be,n 0x00000000(%sr7,%r1) 000000EC 08000240 nop void b() 000000F0: 6BC23FD9 stw %r2,-20(%sp) 000000F4: 37DE0080 ldo 64(%sp),%sp 000000F8 E8200000 bl 0x00000100,%r1 ; get current addr=F8 000000FC D4201C1E depi 0,31,2,%r1 00000100 34213E01 ldo -256(%r1),%r1 ; get code start area 00000104 E85F1FAD bl 0x000000E0,%r2 ; call printf 00000108 B43A0010 addi 8,%r1,%r26 0000010C 4BC23F59 ldw -84(%sp),%r2 00000110 E840C000 bv %r0(%r2) ; return from b 00000114 37DE3F81 ldo -64(%sp),%sp
程序的装入和链接(续4) EXECUTABLE IS DISASSEMBLED HERE 00002000 0009000F ; . . . . 00002004 08000240 ; . . . @ 00002008 48656C6C ; H e l l 0000200C 6F2C2066 ; o , f 00002010 726F6D20 ; r o m 00002014 620A0001 ; b . . . 00002018 48656C6C ; H e l l 0000201C 6F2C2066 ; o , f 00002020 726F6D20 ; r o m 00002024 6D61696E ; m a i n 000020B0 6BC23FD9 stw %r2,-20(%sp) ; main 000020B4 37DE0080 ldo 64(%sp),%sp 000020B8 E8200000 bl 0x000020C0,%r1 000020BC D4201C1E depi 0,31,2,%r1 000020C0 34213E81 ldo -192(%r1),%r1 000020C4 E84017AC bl 0x00003CA0,%r2 000020C8 B43A0040 addi 32,%r1,%r26 000020CC E8400040 bl 0x000020F4,%r2 000020D0 6BC23FD9 stw %r2,-20(%sp) 000020D4 4BC23F59 ldw -84(%sp),%r2 000020D8 E840C000 bv %r0(%r2) 000020DC 37DE3F81 ldo -64(%sp),%sp 000020E0 E8200000 bl 0x000020E8,%r1 ; stub 000020E4 28203000 addil L%6144,%r1 000020E8 E020E772 be,n 0x000003B8(%sr7,%r1) 000020EC 08000240 nop
程序的装入和链接(续5) EXECUTABLE IS DISASSEMBLED HERE 000020F0 6BC23FD9 stw %r2,-20(%sp) ; b 000020F4 37DE0080 ldo 64(%sp),%sp 000020F8 E8200000 bl 0x00002100,%r1 000020FC D4201C1E depi 0,31,2,%r1 00002100 34213E01 ldo -256(%r1),%r1 00002104 E840172C bl 0x00003CA0,%r2 00002108 B43A0010 addi 8,%r1,%r26 0000210C 4BC23F59 ldw -84(%sp),%r2 00002110 E840C000 bv %r0(%r2) 00002114 37DE3F81 ldo -64(%sp),%sp 00003CA0 6BC23FD9 stw %r2,-20(%sp) ; printf 00003CA4 37DE0080 ldo 64(%sp),%sp 00003CA8 6BDA3F39 stw %r26,-100(%sp) 00003CAC 2B7CFFFF addil L%-26624,%dp 00003CB0 6BD93F31 stw %r25,-104(%sp) 00003CB4 343301A8 ldo 212(%r1),%r19 00003CB8 6BD83F29 stw %r24,-108(%sp) 00003CBC 37D93F39 ldo -100(%sp),%r25 00003CC0 6BD73F21 stw %r23,-112(%sp) 00003CC4 4A730009 ldw -8188(%r19),%r19 00003CC8 B67700D0 addi 104,%r19,%r23 00003CCC E8400878 bl 0x00004110,%r2 00003CD0 08000258 copy %r0,%r24 00003CD4 4BC23F59 ldw -84(%sp),%r2 00003CD8 E840C000 bv %r0(%r2) 00003CDC 37DE3F81 ldo -64(%sp),%sp 00003CE0 E8200000 bl 0x00003CE8,%r1 00003CE8 E020E852 be,n 0x00000428(%sr7,%r1)
§4.1.4地址重定位 • 地址映射(地址重定位,地址变换) • 逻辑地址(相对地址,虚地址) • 物理地址(绝对地址,实地址) • 地址映射
地址重定位(续2) • 逻辑地址(相对地址,虚地址) 源程序经过汇编或编译后,形成目标程序,每个目标程序都是以0为基址顺序进行编址的,原来用符号名访问的单元用具体的数据--单元号取代。 这样生成的目标程序占据一定的地址空间,称为作业的逻辑地址空间,简称逻辑空间。在逻辑空间中每条指令的地址和指令中要访问的操作数地址统称为逻辑地址。
地址重定位(续3) • 物理地址(绝对地址,实地址) 内存是由若干个存储单元组成的,每个存储单元有一个编号,这种编号可唯一标识一个存储单元,称为内存地址(或物理地址)。 • 地址映射 为保证CPU执行指令时可正确访问存储单元,需将用户程序中的逻辑地址转换为运行时由机器直接寻址的物理地址,这一过程称为地址映射。
源程序 逻辑地址空间 物理地址空间 0 Load A data1 data1 3456 Load A 200 3456 Load A 200 3456 。 。 BA=1000 100 编译连接 地址映射 1200 200 地址重定位(续4)
地址重定位(续5) • 静态地址重定位 • 静态地址重定位是在程序执行之前由操作系统的重定位装入程序完成的。 • 动态地址重定位 • 动态地址重定位是在程序执行期间进行。
BR 逻辑地址空间 物理地址空间 0 0 1000 … … VR 100 + 1100 200 LOAD A 200 LOAD A 200 … … 200 3456 3456 1200 … … 1300 … 300 可重定位装入方式
§4.2连续分配方式 • 广泛应用于20世纪60-70年代的OS中,它至今仍在内存分配方式中占有一席之地.又可把连续分配方式进一步分为: • 单一连续分配 • 固定分区分配 • 动态分区分配 • 动态重定位分区分配
0xFFF... 用户程序 操作系统 0 §4.2.1 单一连续分配 只能用于单用户、单任务的操作系统中。采用这种存储管理方式时,可把内存分为系统区和用户区两部分. 系统区仅提供给OS使用,通常是放在内存的低址部分;用户区是指除系统区以外的全部内存空间,提供给用户使用。
单一连续分配 • 配置存储器保护机构 ? 用于防止用户程序对操作系统的破坏 DOS,未采取存储器保护措施。这是因为一方面可以节省硬件,另一方面也因为这是可行的。 在单用户环境下,机器由一用户独占,不可能存在其他用户干扰的间题,这时可能出现的破坏行为,也只是用户程序自己去破坏操作系统,其后果并不严重,只是会影响该用户程序的运行,且操作系统也很容易通过系统的再启动而重新装入内存。
§4.2.2固定分区分配 • 最简单的一种可运行多道程序的存储管理方式。 将内存用户空间划分为若干个固定大小的区域,在每个分区中只装入一道作业.这样,把用户空间划分为几个分区,便允许有几道作业并发运行。 • 这种存储管理的方法的主要问题是内存使用效率极低,很快就被淘汰了。
分区4 分区3 分区2 分区1 操作系统 分区4 分区3 分区2 分区1 操作系统 固定分区分配(2) 分区大小相等 分区大小不等 • 缺乏灵活性,当程序很小时,造成内存空间的浪费. 当程序太大时,一个分区又不足以装入该程序,致使该程序无法运行。 • 把内存区划分成含有多个较小的分区、适量的中等分区及少量的大分区。这样,便可根据程序的大小为之分配适当的分区
多个等待队列 分区4 分区3 分区2 分区1 操作系统 分区4 分区3 分区2 分区1 操作系统 单个等待队列 固定分区分配(3)
固定分区分配(4) • 内存分配 为了便于内存分配,通常将分区按大小进行排队,并为之建立一张分区使用表,其中各表项包括每个分区的起始地址、大小及状态(是否已分配)。当有一用户程序要装入时,由内存分配程序检索该表,从中找出一个能满足要求的、尚未分配的分区,将之分配给该程序,然后将该表项中的状态置为‘已分配’;若未找到大小足够的分区,则拒绝为该用户程序分配内存。
§4.2.3 动态分区分配 • 根据进程的实际需要,动态地为之分配内存空间。 • 在实现可变分区分配时,将涉及到分区分配中所用的数据结构、分区分配算法和分区的分配与回收操作这样三个问题。
动态分区分配(2) • 基本思想 • 内存不是预先划分好的 • 作业装入时,根据作业的需求和内存空间的使用情况来决定是否分配 • 若有足够的空间,则按需要分割一部分分区给该进程;否则令其等待内存空间
动态分区分配方案 • 内存管理 • 空闲块表——记录了空闲区起始地址和长度 • 已分配区表 • 内存分配 • 动态分配 • 四种分配算法:首次适应 、循环首次适应 、最佳适应、最坏适应
0K 15K 38K 48K 68K 80K 110K 120K 数据结构 空闲区表 已分配区表
数据结构(2) 空闲区表 0K 15K 38K 48K 已分配区表 68K 80K 85K 98K 110K 120K
首次适应算法FF • FF算法要求空闲分区链以地址递增的次序链接。 • 在分配内存时,从链首开始顺序查找,直至找到一个大小能满足要求的空闲分区为止;然后再按照作业的大小,从该分区中划出一块内存空间分配给请求者,余下的空闲分区仍留在空闲链中.若从链首直至链尾都不能找到一个能满足要求的分区,则此次内存分配失败,返回。 • 问:前一页图中,新增任务,要求长度为27K 该分配哪一段空闲区?
0K 15K 38K 48K 68K 80K 110K 120K 首次适应算法FF(2) FF例题 空闲区表 新增任务,要求内存27K
首次适应算法FF(3) • 算法倾向于优先利用内存中低址部分的空闲分区,从而保留了高址部分的大空闲区。 • 这给为以后到达的大作业分配大的内存空间创造了条件。 • 低址部分不断被划分,会留下许多难以利用的、很小的空闲分区,而每次查找又都是从低址部分开始,这无疑会增加查找可用空闲分区时的开销。
循环首次适应算法 • 在为进程分配内存空间时,不再是每次都从链首开始查找,而是从上次找到的空闲分区的下一个空闲分区开始查找,直至找到一个能满足要求的空闲分区,从中划出一块与请求大小相等的内存空间分配给作业。 • 该算法能使内存中的空闲分区分布得更均匀,从而减少了查找空闲分区时的开销 • 系统中缺乏大的空闲分区。
0K 15K 38K 48K 68K 80K 110K 120K 循环首次适应算法(2) 循环首次适应算法例题 空闲区表 新增任务,要求内存18K
最佳适应算法 • 每次为作业分配内存时,总是把能满足要求、又是最小的空闲分区分配给作业,避免“大材小用”。 • 为加速寻找,该算法要求将所有的空闲分区按其容量以从小到大的顺序形成一个空闲分区链。 • 每次找到的能满足要求的空闲区,必然是最佳的。 • 在宏观上却不一定,因为每次分配后所切割下来的剩余部分总是最小的,这样,在存储器中会留下许多难以利用的小空闲区。
0K 15K 38K 48K 68K 80K 110K 120K 最佳适应算法(2) 最佳适应算法例题 空闲区表 新增任务,要求内存22K
0K 15K 38K 48K 68K 80K 110K 120K 最坏适应算法 • 接到内存申请时,在空闲块表中找到一个不小于请求的最大空块进行分配 (特点:当分割后空闲块仍为较大空块) 空闲区表 新增任务,要求内存12K
回收问题 • 当一个进程(或程序)释放某内存区时,要调用存储区释放算法release,它将首先检查释放区是否与空闲区表(队列)中的其它空闲区相邻,若相邻则合并成一个空闲区,否则,将释放为一个空闲区插入空闲区表(或队列)中的适当位置。 • 考虑:上邻、下邻、上下相邻、上下不相邻
回收问题(2) • A、回收区前后都不是空闲区 • B、回收区之前是空闲区 • C、回收区之后是空闲区 • D、回收区前后都是是空闲区
“碎片”问题 • “碎片”问题 经过一段时间的分配回收后,内存中存在很多很小的空闲块。它们每一个都很小,不足以满足分配要求;但其总和满足分配要求。这些空闲块被称为碎片。 造成存储资源的浪费 整理“碎片”
BR 逻辑地址空间 物理地址空间 0 0 1000 … … VR 100 + 1100 200 LOAD A 200 LOAD A 200 … … 200 3456 3456 1200 … … 1300 … 300 “碎片”问题(2) • 对程序和数据的地址加以修改(变换)