知识框架
概念
内存管理 (MemoryManagement)是操作系统设计中最重要和最复杂的内容之一。操作系统对内存的划分和动态分配,就是内存管理的概念。
内存管理的功能
内存空间的分配与回收:由操作系统完成主存储器空间的分配和管理,使程序员摆脱存储分配的麻烦,提高编程效率。
地址转换:在多道程序环境下, 程序中的逻辑地址与内存中的物理地址不可能一致, 因此存储管理必须提供地址变换功能,把逻辑地址转换成相应的物理地址。
内存空间的扩充:利用虚拟存储技术或自动覆盖技术,从逻辑上扩充内存 。
存储保护:保证各道作业在各自的存储空间内运行,互不干扰。
进程运行的基本原理和要求
程序装入和链接
内存的装入模块在装入内存时,同样有以下三种方式 :
绝对装入:绝对装入程序按照装入模块中的地址,将程序和数据装入内存。由于程序中的逻辑地址与实际内存地址完全相同,故不需对程序和数据的地址进行修改。绝对装入方式只适用于单道程序环境。
可重定位装入:在多道程序环境下,多个目标模块的起始地址通常都是从0开始,程序中的其他地址都是相对于起始地址的,此时应采用可重定位装入方式。
静态重定位的特点是在一个作业装入内存时,必须分配其要求的全部内存空间,如果没有足够的内存,就不能装入该作业。
动态运行时装入:也称为动态重定位, 程序在内存中如果发生移动,就需要采用动态的装入方式。这种方式需要一个重定位寄存器的支持。
动态重定位的特点:
逻辑地址空间与物理地址空间
内存保护
覆盖与交换技术是在多道程序环境下用来扩充内存的两种方法。
覆盖的基本思想
由于程序运行时并非任何时候都要访问程序及数据的各个部分(尤其是大程序),因此可以把用户空间分成一个固定区和若干个覆盖区。
将经常活跃的部分放在固定区, 其余部分按调用关系分段。首先将那些即将要访问的段放入覆盖区,其他段放在外存中,在需要调用前,系统再将其调入覆盖区,替换覆盖区中原有的段。
覆盖技术的特点
打破了必须将一个进程的全部信息装入主存后才能运行的限制,但当同时运行程序的代码量大于主存时仍不能运行。
内存中能够更新的地方只有覆盖区的段,不在覆盖区中的段会常驻内存。
交换(对换)的基本思想
把处于等待状态(或在CPU调度原则下被剥夺运行权利)的程序从内存移到辅存,把内存空间腾出来,这一过程又叫换出;把准备好竞争 CPU 运行的程序从辅存移到内存,这一过程又称为换入。
交换需要注意问题
覆盖&交换联系
交换技术主要是在不同进程(或作业)之间进行,而覆盖则用于同一个程序或进程中。
由于覆盖技术要求给出程序段之间的覆盖结构,使得其对用户和程序员不透明,所以对于主存无法存放用户程序的矛盾,现代操作系统是通过虚拟内存技术来解决的,覆盖技术则己成为历史;而交换技术在现代操作系统中仍具有较强的生命力。
概述
连续分配方式,是指为一个用户程序分配一个连续的内存空间,比如说某用户需要1GB的内存空间,它就在内存空间中分配一块连续的 1GB的空间给用户。
它主要包括单一连续分配、 固定分区分配和动态分区分配。
概述
内存在此方式下分为系统区和用户区,系统区仅提供给操作系统使用,通常在低地址部分;用户区是为用户提供的、除系统区之外的内存空间。 这种方式无需进行内存保护。
特点
优点:简单、无外部碎片,可以采用覆盖技术,不需要额外的技术支持。
缺点:只能用于单用户、单任务的操作系统中,有内部碎片,存储器的利用率极低。
概述
固定分区分配是最简单的一种多道程序存储管理方式,它将用户内存空间划分为若干个固定大小的区域,每个分区只装入一道作业。
当有空闲分区时,便可以再从外存的后备作业队列中, 选择适当大小的作业装入该分区,如此循环。
固定分区分配的两种方法:
分区大小相等:用于利用一台计算机去控制多个相同对象的场合, 缺乏灵活性。
分区大小不等:划分为含有多个较小的分区、适量的中等分区及少量的大分区。
为便于内存分配,通常将分区按大小排队, 并为之建立一张分区说明表,其中各表项包括每个分区的起始地址、大小及状态(是否己分自己)。 当有用户程序要装入时,便检索该表,以找到合适的分区给予分配并将其状态置为“己分配”;未找到合适分区则拒绝为该用户程序分配内存。
分区方式存在问题
概述
动态分区分配又称为可变分区分配,是一种动态划分内存的分区方法。这种分区方法不预先将内存划分,而是在进程装入内存时,根据进程的大小动态地建立分区 ,并使分区的大小正好适合进程的需要。因此系统中分区的大小和数目是可变的。
外部碎片:在所有分区外的存储空间会变成越来越多的碎片,与固定分区中的内部碎片正好相对。
紧凑 (Compaction)技术:操作系统不时地对进程进行移动和整理,需要动态重定位寄存器的支持,且相对费时。
分配策略算法
首次适应 (First Fit) 算法:空闲分区以地址递增的次序链接。分配内存时顺序查找,找到大小能满足要求的第一个空闲分区。
最佳适应 ( Best Fit )算法:空闲分区按容量递增形成分区链,找到第一个能满足要求的空闲分区。
最坏适应 ( Worst Fit )算法:又称最大适应 ( Largest Fit )算法,空闲分区以容量递减的次序链接。找到第一个能满足要求的空闲分区,也就是挑选出最大的分区。
邻近适应 ( Next Fit )算法:又称循环首次适应算法,由首次适应算法演变而成。不同之处是分配内存时从上次查找结束的位置开始继续查找。
在这几种方法中,首次适应算法不仅是最简单的,而且通常也是最好和最快的。
概述
非连续分配允许一个程序分散地装入到不相邻的内存分区中。如果采用非连续分配管理方式,作业所要求的1GB内存空间可以分散地分配 在内存的各个区域,当然,这也需要额外的空间去存储它们(分散区域)的索引,使得非连续分配方式的存储密度低于连续存储方式。
非连续分配管理方式根据分区的大小是否固定分为分页存储管理方式和分段存储管理方式。
概述
分页存储管理方式中,根据运行作业时是否要把作业的所有页面都装入内存才能运行分为基本分页存储管理方式和请求分页存储管理方式。
基本分页存储管理方式
分页思想:把主存空间划分为大小相等且固定的块,块相对较小,作为主存的基本单位。每个进程也以块为单位进行划分,进程在执行时,以块为单位逐个申请主存中的块空间。
分页的方法从形式上看,像分区相等的固定分区技术,分页管理不会产生外部碎片。
**每个进程平均只产生半个块大小的内部碎片(也称页内碎片) **。
页面和页面大小
地址结构
页表
基本地址变换机构
地址变换机构的任务是将逻辑地址转换为内存中物理地址,地址变换是借助于页表实现的。
在系统中通常设置一个页表寄存器(PTR),存放页表在内存的始址F和页表长度M。
假设页面大小为L,逻辑地址A到物理地址E的变换过程如下(逻辑地址、页号、 每页的长度都是十进制数):
计算页号P ( P = A / L P=A/L P=A/L) 和页内偏移量 W ( W = A ( m o d L ) W=A\pmod L W=A(modL))。
比较页号P和页表长度M,若 P ≤ M P\leq M P≤M,则产生越界中断,否则继续执行。
页表中页号P对应的页表项地址=页表起始地址 F+页号 P*页表项长度,取出该页表项内容b,即为物理块号。
计算 E = b ∗ L + W E=b*L+W E=b∗L+W,用得到的物理地址E去访问内存。
页式管理中地址空间是一维的。
具有快表的地址变换机构
问题:若页表全部放在内存中,则存取一个数据或一条指令至少要访问两次内存:第一次是访问页表,第 二 次才根据该地址存取数据或指令,这种方法比通常执行指令的速度慢了一半。
优化:地址变换机构中增设了一个具有并行查找能力的高速缓冲存储器一快表(与此对应,主存中的页表也常称为慢表),又称联惜想寄存器 (TLB),用来存放当前访问的若干页表项,以加速地址变换的过程。
快表分页机制地址变换过程:
CPU给出逻辑地址后,由硬件进行地址转换并将页号送入高速缓存寄存器,并将此页号 与快表中的所有页号进行比较。
果找到匹配的页号,说明所要访问的页表项在快表中 , 则直接从中取出该页对应的页框号,与页内偏移量拼接形成物理地址。
如果没有找到,则需要访问主存中的页表,在读出页表项后 ,应同时将其存入快表,以便后面可能的再次访问。
但若快表己满,则必须按照一定的算法对旧的页表项进行替换。
作用:一般快表的命中率可以达到则以上,这样,分页带来的速度损失就降低到附以下。 快表的有效性是基于著名的局部性原理。
两级页表
二级页表实际上就是在原有页表结构上再加了一层页表
作用:建立多级页表的目的在于建立索引,这样不用浪费主存空间去存储无用的页表项,也不用盲目地顺序式查找页表项。
背景
分页管理方式是从计算机的角度考虑设计的,以提高内存的利用率,提升计算机的性能,且分页通过硬件机制实现,对用户完全透明;而分段管理方式的提出则是考虑了用户和程序员,以满足方便编程、信息保护和共享、动态增长及动态链接等多方面的需要。
分段
段式管理方式按照用户进程中的自然段划分逻辑空间。逻辑地址由段号 S 与段内偏移量 W 两部分组成。( 连续地址空间:段内要求连续, 段间不要求连续 ,因此整个作业的地址空间是二维的)
在页式系统中,逻辑地址的页号和页内偏移量对用户是透明的,但在段式系统中,段号和段内偏移量必须由用户显示提供,在高级程序设计语言中,这个工作由编译程序完成。
段表
每个进程都有一张逻辑空间与内存空间映射的段表,其中每一个段表项对应进程的一个段,段表项记录该段在内存中的起始地址和段的长度。
在配置了段表后,执行中的进程可通过查找段表,找到每个段所对应的内存区。 可见, 段表用于实现从逻辑段到物理内存区的映射。
地址变换机构
为了实现进程从逻辑地址到物理地址的变换功能,在系统中设置了段表寄存器,用于存放段表始址F和段表长度M。
从逻辑地址A到物理地址E之间的地址变换过程:
段的共享与保护
在分段系统中,段的共享是通过两个作业的段表中相应表项指向被共享的段的同一个物理副本来实现的。
当一个作业正从共享段中读取数据时,必须防止另一个作业修改此共享段中的数据。不能修改的代码称为纯代码或可重入代码(它不属于临界资源),这样的代码和不能修改的数据是可以共享的,而可修改的代码和数据则不能共享。
与分页管理类似,分段管理的保护方法主要有两种:① 存取控制保护,② 地址越界保护。
分段管理的地址空间是二维的。
概述
页式存储管理能有效地提高内存利用率 ,而分段存储管理能反映程序的逻辑结构井有利于段的共享。如果将这两种存储管理方法结合起来,就形成了段页式存储管理方式。
在段页式系统中,作业的地址空间首先被分成若干个逻辑段, 每段都有自己的段号,然后再将每一段分成若干个大小固定的页。对内存空间的管理仍然和分页存储管理一样,将其分成若干个和页面大小相同的存储块,对内存的分配以存储块为单位。
在段页式系统中,作业的逻辑地址分为三部分:段号、页号和页内偏移量。
注意:在一个进程中,段表只有一个,而页表可能有多个。
在进行地址变换时,首先通过段表查到页表起始地址,然后通过页表找到页帧号,最后形成物理地址。段页式管理的地址空间是二维的。
传统存储管理方式的特征
局部性原理
局部性原理表现在以下两个方面:
虚拟内存技术实际上就是建立了“内存一外存”的两级存储器的结构,利用局部性原理实现高速缓存。
虚拟存储器的定义和特征
定义:在程序装入和执行过程中,操作系统提供了部分装入、请求调入和置换功能(将程序所需要的部分调入内存,将暂时不使用的内容换出到外存上 ),好像为用户提供了一个比实际内存大得多但实际上并不存在的存储器,称为虚拟存储器。
主要特征:
虚拟内存技术的实现
虚拟内存的实现需要建立在离散分配的内存管理方式的基础上。
虚拟内存实现方式:
虚拟内存硬件支持:
一 定容量的内存和外存。
页表机制(或段表机制),作为主要的数据结构。
中断机构,当用户程序要访问的部分尚未调入内存,则产生中断。
地址变换机构,逻辑地址到物理地址的变换。
概述
请求分页系统建立在基本分页系统基础之上,为了支持虚拟存储器功能而增加了请求调页功能和页面置换功能。请求分页是目前最常用的一种实现虚拟存储器的方法。
在请求分页系统中,只要求将当前需要的一部分页面装入内存,便可以启动作业运行。在作业执行过程中,当所要访问的页面不在内存时,再通过调页功能将其调入,同时还可以通过置换功能将暂时不用的页面换出到外存上,以便腾出内存空间。
页表机制
请求分页系统在请求页表项中增加了以下四个宇段:
缺页中断机构
缺页中断与一般的中断区别:
在指令执行期间产生和处理中断信号 ,而非一条指令执行完后,属于内部中断。
一条指令在执行期间,可能产生多次缺页中断。
地址变换机构
请求分页系统中的地址变换机构,是在分页系统地址变换机构的基础上,为实现虚拟内存,又增加了某些功能而形成的。
地址变换过程:
概念
进程运行时,若其访问的页面不在内存而需将其调入,但内存已无空闲空间时,就需要从内存中调出一页程序或数据,送入磁盘的对换区。而选择调出页面的算法就称为页面置换算法。(决定应该换入哪页换出哪页)
好的页面置换算法应有较低的页面更换频率, 也就是说,应将以后不会再访问或者以后较长时间内不会再访问的页面先调出。
常见置换算法
概述
最佳 (Optimal, OPT) 置换算法所选择的被淘汰页面将是以后永不使用的,或者是在最长时间内不再被访问的页面,这样可以保证获得最低的缺页率。
但由于人们目前无法预知进程在内存下的若干页面中哪个是未来最长时间内不再被访问的, 因而该算法无法实现。
最佳置换算法可以用来评价其他算法。
概述
优先淘汰最早进入内存的页面,亦即在内存中驻留时间最久的页面。该算法实现简单 , 只需 把调入内存的页面根据先后次序链接成队列,设置一个指针总指向最早的页面。
FIFO算法还会产生当所分配的物理块数增大而页故障数不减反增的异常现象,这是由 Belady 于 1969 年发现 , 故称为 Belady 异常。只有 FIFO 算法可能出现 Belady 异常, 而 LRU 和 OPT 算法永远不会出现 Belady 异常。
概述
选择最近最长时间未访问过的页面予以淘汰,它认为过去一段时间内未访问过的页面,在最近的将来可能也不会被访问。
该算法为每个页面设置一个访问字段,来记录页面自上次被访问以来所经历的时间,淘汰页面时选择现有页面中值最大的予以淘汰。
LRU 性能较好,但需要寄存器和栈的硬件支持。LRU 是堆栈类的算法。理论上可以证明, 堆栈类算法不可能出现 Belady 异常。FIFO 算法基于队列实现 ,不是堆栈类算法。
概述
因为算法要循环扫描缓冲区检查各页面的情况,像时钟的针一样转动,所以叫CLOCK算法,又称为最近未用(Not Recently Used, NRU)算法。
CLOCK 算法的性能比较接近LRU,而通过增加使用的位数目,可以使得 CLOCK 算法更加高效。在使用位的基础上再增加一个修改位,则得到改进型的CLOCK置换算法。
算法执行操作步骤
改进型的 CLOCK 算法优于简单 CLOCK 算法之处,在于替换时首选没有变化的页。由于修改过的页在被替换之前必须写回,因而这样做会节省时间。
驻留集大小
现代操作系统通常采用三种策略:
调入页面的时机
为确定系统将进程运行时所缺的页面调入内存的时机,可采取以下两种调页策略:
预调入实际上就是运行前的调入,请求调页实际上就是运行期间调入。一般情况下 ,两种调页策略会同时使用。
从何处调入页面
请求分页系统中的外存分为两部分:用于存放文件的文件区和用于存放对换页面的对换区。
对换区通常是采用连续分配方式,而文件区采用离散分配方式,故对换区的磁盘 I/O 速度比文件区的更快。
从何处调入页面有三种情况:
概述
在页面置换过程中的一种最糟糕的情形是,刚刚换出的页面马上又要换入主存 ,刚刚换入的页面马上就要换出主存,这种频繁的页面调度行为称为抖动 ,或颠簸。
如果一个进程在换页上用的时间多于执行时间 , 那么这个进程就在颠簸。
原因
频繁的发生缺页中断(抖动),其主要原因是某个进程频繁访问的页面数目高于可用的物理页帧数目。
概念
**工作集 (或驻留集)**是指在某段时间间隔内,进程要访问的页面集合。经常被使用的页面需要在工作集中,而长期不被使用的页面要从工作集中被丢弃。
为了防止系统出现抖动现象,需要选择合适的工作集大小。
原理
让操作系统跟踪每个进程的工作集,并为进程分配大于其工作集的物理块。
如果还有空闲物理块,则可以再调一个进程到内存以增加多道程序数。
如果所有工作集之和增加以至于超过了可用物理块的总数, 那么操作系统会暂停一个进程,将其页面调出并且将其物理块分配给其他进程,防止出现抖动现象。
正确选择工作集的大小,对存储器的利用率和系统吞吐量的提高 ,都将产生重要影响。
为什么要引入虚拟内存
在物理上扩展内存相对有限的条件下,以一些其他可行的方式在逻辑上来扩充内存。
虚拟内存空间的大小决定因素
虚拟存储器的大小由计算机的地址结构决定,并非是内存和外存的简单相加。
虚存的大小要同时满足 2 个条件:
实际虚存的容量是取条件1、2的交集,也就是说,两个条件都要满足,光满足一个是不行的。
虚拟内存优缺点
优点:虚拟内存使用了外存上的空间来扩充内存的空间,通过一定的换入换出,使得整个系统在逻辑上能够使用一个远远超出其物理内存大小的内存容量。
缺点:虚拟内存技术调换页面时需要访问外存,会导致平均访存时间下降,如果使用了不合适的替换算法,则会大大降低系统性能。
分页管理方式和分段管理方式对比
本章知识架构图