操作系统内存管理:总的来说,操作系统内存管理包括物理内存管理
和虚拟内存管理
物理内存管理:
包括程序装入等概念、交换技术、连续分配管理方式(块式)和非连续分配管理方式(分页、分段、段页式)
虚拟内存管理:
虚拟内存管理包括虚拟内存概念、请求分页管理方式、页面置换算法
、页面分配策略、工作集和抖动。
一、 计算机的存储体系
内存是计算机很重要的一个资源,因为程序只有被加载到内存中才可以运行
;此外,CPU所需要的指令与数据也都是来自内存的
。可以说,内存是影响计算机性能的一个很重要的因素
分层存储器体系
在介绍内存管理的细节前,先要了解一下分层存储器体系:
大部分的计算机都有一个存储器层次结构,即少量的非常快速、昂贵、易变的高速缓存(cache)
;若干兆字节的中等速度、中等价格、易变的主存储器(RAM)
;数百兆或数千兆的低速、廉价、不易变的磁盘
。这些资源的合理使用与否直接关系着系统的效率。
CPU缓存(Cache Memory):是位于CPU与内存之间的临时存储器
,它的容量比内存小的多但是交换速度却比内存要快得多
。缓存的出现主要是为了解决CPU运算速度与内存 读写速度不匹配的矛盾
,因为CPU运算速度要比内存读写速度快很多,这样会使CPU花费很长时间等待数据到来或把数据写入内存
。
计算机是一种数据处理设备,它由CPU和内存以及外部设备
组成。CPU负责数据处理,内存负责存储,外部设备负责数据的输入和输出,它们之间通过总线连接在一起
。CPU内部主要由控制器、运算器和寄存器组成
。控制器负责指令的读取和调度,运算器负责指令的运算执行,寄存器负责数据的存储,它们之间通过CPU内的总线连接在一起
。每个外部设备(例如:显示器、硬盘、键盘、鼠标、网卡等等)则是由外设控制器、I/O端口、和输入输出硬件组成。外设控制器负责设备的控制和操作,I/O端口负责数据的临时存储,输入输出硬件则负责具体的输入输出,它们间也通过外部设备内的总线连接在一起
。
在这套设计思想(冯.诺依曼体系架构)里面: 总是有一部分负责控制、一部分负责执行、一部分则负责存储,它之间进行交互以及接口通信则总是通过总线来完成
计算存储的层次结构
大部分的计算机都有一个存储器层次结构:
高速缓存(cache): 少量的非常快速、昂贵、易变的高速缓存(cache);
主存储器(RAM): 若干兆字节的中等速度、中等价格、易变的主存储器(RAM);
磁盘: 数百兆或数千兆的低速、廉价、不易变的磁盘。
这些资源的合理使用与否直接关系着系统的效率。
二、内存使用演化
没有内存抽象的年代
在早些的操作系统中,并没有引入内存抽象的概念。程序直接访问和操作的都是物理内存,内存的管理也非常简单,除去操作系统所用的内存之外,全部给用户程序使用,想怎么折腾都行,只要别超出最大的容量
1、无内存抽象存在的问题:
这条指令会毫无想象力的将物理地址1000中的内容赋值给寄存器。不难想象,这种内存操作方式使得操作系统中存在多进程变得完全不可能,比如MS-DOS,你必须执行完一条指令后才能接着执行下一条。如果是多进程的话,由于直接操作物理内存地址,当一个进程给内存地址1000赋值后,另一个进程也同样给内存地址赋值,那么第二个进程对内存的赋值会覆盖第一个进程所赋的值,这回造成两条进程同时崩溃。
带来两个问题:
用户程序可以访问任意内存,容易破坏操作系统,造成崩溃
同时运行多个程序特别困难
虚拟内存
很多情况下,现有内存无法满足仅仅一个大进程的内存要求。物理内存不够用的情况下,如何解决呢?
覆盖overlays:在早期的操作系统曾使用覆盖技术来解决这个问题,将一个程序分为多个块,基本思想是先将块0加入内存,块0执行完后,将块1加入内存。
依次往复,这个解决方案最大的问题是需要程序员去程序进行分块,这是一个费时费力让人痛苦不堪的过程。后来这个解决方案的修正版就是虚拟内存。
交换swapping:可以将暂时不能执行的程序(进程)送到外存中,从而获得空闲内存空间来装入新程序(进程)
,或读人保存在外存中而处于就绪状态的程序。
虚拟内存:虚拟内存的基本思想是,每个进程都有独立的逻辑地址空间,内存被分为大小相等的多个块,称为页(Page).每个页都是一段连续的地址
。对于进程来看,逻辑上貌似有很多内存空间,其中一部分对应物理内存上的一块(称为页框,通常页和页框大小相等),还有一些没加载在内存中的对应在硬盘上。
三. 物理内存:连续分配存储管理方式
连续分配是指为一个用户程序分配连续的内存空间。连续分配有单一连续存储管理和分区式储管理两种方式。
3.1 单一连续存储管理
在这种管理方式中,内存被分为两个区域:系统区和用户区。应用程序装入到用户区,可使用用户区全部空间
。其特点是,最简单,适用于单用户、单任务的操作系统。这种方式的最大优点就是易于管理
。但也存在着一些问题和不足之处,例如对要求内存空间少的程序,造成内存浪费;程序全部装入,使得很少使用的程序部分也占用—定数量的内存
。
3.2 分区式存储管理
为了支持多道程序系统和分时系统,支持多个程序并发执行
,引入了分区式存储管理。分区式存储管理是把内存分为一些大小相等或不等的分区,操作系统占用其中一个分区,其余的分区由应用程序使用,每个应用程序占用一个或几个分区
。分区式存储管理虽然可以支持并发,但难以进行内存分区的共享。
分区式存储管理引人了两个新的问题:内碎片和外碎片。
内碎片是占用分区内未被利用的空间,外碎片是占用分区之间难以利用的空闲分区(通常是小空闲分区)。
为实现分区式存储管理,操作系统应维护的数据结构为分区表或分区链表。表中各表项一般包括每个分区的起始地址、大小及状态(是否已分配)。
分区式存储管理常采用的一项技术就是内存紧缩(compaction)。
3.2.1 固定分区(nxedpartitioning)。
固定式分区的特点是把内存划分为若干个固定大小的连续分区
。分区大小可以相等:这种作法只适合于多个相同程序的并发执行(处理多个类型相同的对象)。分区大小也可以不等:有多个小分区、适量的中等分区以及少量的大分区。根据程序的大小,分配当前空闲的、适当大小的分区。
优点:易于实现,开销小。
缺点主要有两个:内碎片造成浪费;分区总数固定,限制了并发执行的程序数目
。
3.2.2动态分区(dynamic partitioning)
动态分区的特点是动态创建分区:在装入程序时按其初始要求分配,或在其执行过程中通过系统调用进行分配或改变分区大小
。与固定分区相比较其优点是:没有内碎片
。但它却引入了另一种碎片——外碎片
。动态分区的分区分配就是寻找某个空闲分区,其大小需大于或等于程序的要求。若是大于要求,则将该分区分割成两个分区,其中一个分区为要求的大小并标记为“占用”,而另一个分区为余下部分并标记为“空闲”
。分区分配的先后次序通常是从内存低端到高端。动态分区的分区释放过程中有一个要注意的问题是,将相邻的空闲分区合并成一个大的空闲分区
。
最先适配法(nrst-fit):按分区在内存的先后次序从头查找
,找到符合要求的第一个分区进行分配
。该算法的分配和释放的时间性能较好,较大的空闲分区可以被保留在内存高端。但随着低端分区不断划分会产生较多小分区,每次分配时查找时间开销便会增大
。
下次适配法(循环首次适应算法 next fit):按分区在内存的先后次序,从上次分配的分区起查找(到最后{区时再从头开始},找到符合要求的第一个分区进行分配
。该算法的分配和释放的时间性能较好,使空闲分区分布得更均匀,但较大空闲分区不易保留
。
最佳适配法(best-fit):按分区在内存的先后次序从头查找,找到其大小与要求相差最小的空闲分区进行分配
。从个别来看,外碎片较小;但从整体来看,会形成较多外碎片优点是较大的空闲分区可以被保留。
最坏适配法(worst- fit):按分区在内存的先后次序从头查找,找到最大的空闲分区进行分配。基本不留下小空闲分区
,不易形成外碎片。但由于较大的空闲分区不被保留,当对内存需求较大的进程需要运行时,其要求不易被满足。
3.3 伙伴系统
固定分区和动态分区方式都有不足之处。固定分区方式限制了活动进程的数目,当进程大小与空闲分区大小不匹配时,内存空间利用率很低。动态分区方式算法复杂,回收空闲分区时需要进行分区合并等,系统开销较大
。伙伴系统方式是对以上两种内存方式的一种折衷方案。
伙伴系统规定,无论已分配分区或空闲分区,其大小均为 2 的 k 次幂,k 为整数, l≤k≤m,其中:
2^1 表示分配的最小分区的大小,
2^m 表示分配的最大分区的大小,
通常2^m是整个可分配内存的大小。
假设系统的可利用空间容量为2^ m个字, 则系统开始运行时, 整个内存区是一个大小为2^m的空闲分区。在系统运行过中, 由于不断的划分,可能会形成若干个不连续的空闲分区,将这些空闲分区根据分区的大小进行分类,对于每一类具有相同大小的所有空闲分区,单独设立一个空闲分区双向链表。这样,不同大小的空闲分区形成了k(0≤k≤m)个空闲分区链表。
3.4 内存紧缩(内存碎片化处理)
内存紧缩:将各个占用分区向内存一端移动,然后将各个空闲分区合并成为一个空闲分区。
这种技术在提供了某种程度上的灵活性的同时,也存在着一些弊端,例如:对占用分区进行内存数据搬移占用CPU时间
a 紧缩前 b紧缩后
3.5 覆盖技术
引入覆盖 (overlay)技术的目标是在较小的可用内存中运行较大的程序。这种技术常用于多道程序系统之中,与分区式存储管理配合使用。
覆盖技术的原理:一个程序的几个代码段或数据段,按照时间先后来占用公共的内存空间。将程序必要部分(常用功能)的代码和数据常驻内存;可选部分(不常用功能)平时存放在外存(覆盖文件)中,在需要时才装入内存。不存在调用关系的模块不必同时装入到内存,从而可以相互覆盖。
在任何时候只在内存中保留所需的指令和数据;当需要其它指令时,它们会装入到刚刚不再需要的指令所占用的内存空间;
如在同一时刻,CPU只能执行B,C中某一条。B,C之间就可以做覆盖。
3.6 交换技术
交换 (swapping)技术在多个程序并发执行时,可以将暂时不能执行的程序(进程)送到外存中,从而获得空闲内存空间来装入新程序(进程)
,或读人保存在外存中而处于就绪状态的程序。交换单位为整个进程的地址空间。交换技术常用于多道程序系统或小型分时系统中
,因为这些系统大多采用分区存储管理方式。与分区式存储管理配合使用又称作“对换”或“滚进/滚出” (roll-in/roll-out)。
原理:暂停执行内存中的进程,将整个进程的地址空间保存到外存的交换区中(换出swap out),而将外存中由阻塞变为就绪的进程的地址空间读入到内存中,并将该进程送到就绪队列
(换入swap in)。
交换技术优点之一是增加并发运行的程序数目,并给用户提供适当的响应时间
;与覆盖技术相比交换技术另一个显著的优点是不影响程序结构。交换技术本身也存在着不足,例如:对换人和换出的控制增加处理器开销
;程序整个地址空间都进行对换,没有考虑执行过程中地址访问的统计特性。
四. 物理内存非连续:页式和段式存储管理
在前面的几种存储管理方法中,为进程分配的空间是连续的,使用的地址都是物理地址
。如果允许将一个进程分散到许多不连续的空间,就可以避免内存紧缩,减少碎片
。基于这一思想,通过引入进程的逻辑地址,把进程地址空间与实际存储空间分离,增加存储管理的灵活性。地址空间和存储空间两个基本概念的定义如下:
地址空间:将源程序经过编译后得到的目标程序,存在于它所限定的地址范围内,这个范围称为地址空间。地址空间是逻辑地址的集合
。
存储空间:指主存中一系列存储信息的物理单元的集合,这些单元的编号称为物理地址存储空间是物理地址的集合
。
根据分配时所采用的基本单位不同,可将离散分配的管理方式
分为以下三种:
页式存储管理、段式存储管理和段页式存储管理
。其中段页式存储管理是前两种结合的产物。
页式和段式管理区别
页式和段式系统有许多相似之处。比如,两者都采用离散分配方式,且都通过地址映射机构来实现地址变换
。但概念上两者也有很多区别,主要表现在:
-
需求:是信息的物理单位,
分页是为了实现离散分配方式,以减少内存的碎片,提高内存的利用率
。或者说,分页仅仅是由于系统管理的需要,而不是用户的需要。段是信息的逻辑单位,它含有一组其意义相对完整的信息。分段的目的是为了更好地满足用户的需要
。
一条指令或一个操作数可能会跨越两个页的分界处,而不会跨越两个段的分界处
。 -
大小:
页大小固定且由系统决定
,把逻辑地址划分为页号和页内地址两部分,是由机器硬件实现的
。段的长度不固定,且决定于用户所编写的程序
,通常由编译系统在对源程序进行编译时根据信息的性质来划分。 -
逻辑地址表示:
页式系统地址空间是一维的
,即单一的线性地址空间,程序员只需利用一个标识符,即可表示一个地址。分段的作业地址空间是二维的,程序员在标识一个地址时,既需给出段名,又需给出段内地址
。 -
段比页大,因而段表比页表短,可以缩短查找时间,提高访问速度
。
页式存储管理
将程序的逻辑地址空间划分为固定大小的页(page),而物理内存划分为同样大小的页框(page frame)。程序加载时,可将任意一页放人内存中任意一个页框,这些页框不必连续,从而实现了离散分配
。该方法需要CPU的硬件支持,来实现逻辑地址和物理地址之间的映射
。在页式存储管理方式中地址结构由两部构成,前一部分是页号,后一部分为页内地址w
(位移量),如图4所示:
页式管理方式的优点是:
1)没有外碎片,每个内碎片不超过页大小
2)比前面所讨论的几种管理方式的最大进步是,一个程序不必连续存放。
3)便于改变程序占用空间的大小(主要指随着程序运行,动态生成的数据增多,所要求的地址空间相应增长)。
缺点是:要求程序全部装入内存,没有足够的内存,程序就不能执行。
在为进程分配内存时,以块为单位
将进程中的若干个页
分别装入到多个可以不相邻接的物理块中
。由于进程的最后一页经常装不满一块而形成了不可利用的碎片,称之为“页内碎片”
。
为了能在内存中找到每个页所对应的物理块
。为此,系统又为每个进程建立了一张页面映像表,简称页表
。在进程地址空间内的所有页(0~n),依次在页表中有一页表项,其中记录了相应页在内存中对应的物理块号
段式存储管理
在分段存储管理方式中,作业的地址空间被划分为若干个段,每个段定义了一组逻辑 信息
。例如,有主程序段 MAIN、子程序段 X、数据段 D 及栈段 S 等。每个段都有一个段号
,每个段都从 0开始编址,并采用一段连续的地址空间。段的长度由相应的逻辑信息组的长度决定,因而各段长度不等
。整个作业的地址空间由于是分成多个段,因而是二维的,亦即,其逻辑地址由段号(段名)和段内地址
所组成。
分段系统的一个突出优点,是易于实现段的共享,即允许若干个进程共享一个或多个分段
,且对段的保护也十分简单易行。在分页系统中,虽然也能实现程序和数据的共享,但远不如分段系统来得方便
段页式存储管理
段页式系统的基本原理,是分段和分页原理的结合,即先将用户程序分成若干个段,再把每个段分成若干个页,并为每一个段赋予一个段名
。在段页式系统中,其地址结构由段号、段内页号及页内地址
三部分所组成,如下图是其地址映射过程
页面置换算法
OPT(最佳页面置换算法) :最佳(Optimal, OPT)置换算法所选择的被淘汰页面将是以后永不使用的,或者是在最长时间内不再被访问的页面
,这样可以保证获得最低的缺页率。但由于人们目前无法预知进程在内存下的若千页面中哪个是未来最长时间内不再被访问的,因而该算法无法实现
。一般作为衡量其他置换算法的方法。
FIFO(First In First Out)(先进先出页面置换算法) : 总是淘汰最先进入内存的页面,即选择在内存中驻留时间最久的页面进行淘汰
。
LRU (Least Currently Used)(最近最久未使用页面置换算法) :LRU算法赋予每个页面一个访问字段,用来记录一个页面自上次被访问以来所经历的时间 T,当须淘汰一个页面时,选择现有页面中其 T 值最大的
,即最近最久未使用的页面予以淘汰。
LFU (Least Frequently Used)(最少使用页面置换算法) : 该置换算法选择在之前时期使用最少的页面作为淘汰页
。