计算机内存管理

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

计算机内存管理策略
【摘要】本文从计算机的硬件结构和运行机理出发,导出计算机内存管理的重要性,并提出内存管理所要包含的4个方面内容。

然后以操作系统发展历史为主线,对单一连续分区存储管理、固定分区存储管理、可变分区存储管理、分页式存储管理、分段式存储管理5中内存管理方案进行分析,详细地介绍了各种管理策略具体实现以及各自的优劣。

在操作系统出现之前,程序曾经是存储在卡片上,计算机每读取一张卡片就执行一条指令,程序的执行过程是直接从卡片到执行。

这种从外部存储媒介上直接执行指令的做法效率极其低下,而且灵活性较差。

为了解决这一问题,人们想到将需要运行的程序预先加载到内部存储器,再自动从内部存取器读取指令并执行,从而提高计算机的效率与灵活性。

这一想法导致计算机硬件系统和软件系统都发生革命性的变化。

目前计算机硬件系统一般由处理机、存储系统和输入输出(I/O)系统构成。

其中存储系统用于存取包括程序代码和数据在内的各种信息,起到缓解负责执行程序的处理器与实现程序输入/输出系统之间速度严重不匹配的矛盾。

出于功用、性能、价格等方面的考虑,计算机存储系统并不是一个单独的存储器件,而是由不同的存储介质构成的一个复杂的多层次的存储体系,包括高速缓存、内存和外存。

高速缓存的由硬件寄存器组构成,其特点是速度最快、价格高、容量小,一般用于存放高频指令与数据;外存容量最大,价格也最低,但是读取速度相对很慢,主要用来存放程序的所有代码与数据,是程序与数据的持久完整集合;内存速度比高速缓存慢,但是比外存又快很多量级,价格适中,容量高于缓存而低于外存,用来存放操作系统内核、用户程序指令与程序运行所需数据,程序运行时,CPU直接从内存读取指令和数据。

尽管内存速度与处理器速度有一定差距,但是这种程序执行的方式仍然极大地提高了计算机的运行效率。

冯·诺依曼体系的计算机都要求程序首先装入内存才能运行,能否合理地使用内存很大程度上影响到整个计算机的正常运行以及系统性能。

因此操作系统要能够很好地管理计算机系统中的重要资源——内存,使得它按规则并被高效地使
用,这是操作系统的起码要求。

1
计算机内存管理主要包括四个方面的内容:内存分配与回收、内存地址映射、内存共享与保护和内存扩充。

内存分配与回收:内存分配主要是对将要驻留在内存中的每道程序和数据分配一定的内存空间,每道程序都有自己专属的地址空间,同时要求程序在运行时申请更多的地址空间,以满足数据段和程序段的可能动态增长的要求。

2当程序运行结束之后,就需要将之前分配给该程序的内存空间回收,以分配给其他程序使用。

内存地址映射:从硬件层次来讲,内存时由一个一个的存储单元构成,每个单元能被访问与否受到地址解码芯片的控制,每个存储单元对应一个唯一的地址,该地址称为“绝对地址”或“物理地址”。

要访问某个地址单元中的数据时,需要CPU向地址总线发出相应的地址信号,选中该存储单元。

但是对于多道编程的系统,计算机内存中同时转载了多个程序,程序员在编程之前根本无法预测程序将会被装载到内存中的什么位置,就算是单道编程的系统也会因为硬件配置和系统不同而装载位置不同。

那么程序员编程时只能在一个相对的地址上进行编程,称为“逻辑地址”或“虚地址”,并假设程序的首地址为0,整个内存空间中只有自己一个程序。

那么在实际运行时,就要求操作系统能够根据程序的实际转载位置和程序的虚拟地址计算出各条指令和数据的物理地址,这个翻译的过程就是地址映射。

内存共享与保护:在多道编程的系统中,程序之间往往会存在着协作,或是使用相同的程序代码,为了使程序之间能够进行交流,也为了节省内存空间,提高内存利用率,多道程序有时需要能够访问同一个内存分区中的数据,使得这些程序的物理空间出现了交叉的部分,这就是内存共享。

同时,每道程序有自己私有的空间,为保证程序运行的正确性,该部分空间不允许其他程序访问和修改,这就需要内存保护,保证“私有财产神圣不可侵犯”。

内存扩充:这里所说的内存扩充并不是指硬件上的扩充,而是指用存储管理软件来实现的逻辑扩充,用到的技术就是虚拟内存。

作业运行时系统并不将其全
1 引自《计算机操作系统》第102页,刘腾红、络正华编著,清华大学出版社出版。

2引自《计算机操作系统》第80页,冯裕忠、方智、周舫编著,清华大学出版社出版。

部程序装入内存,而是只装入当前需要运行的那一部分,其他的仍在外存。

若进程需要时再把所需部分调入,以保证大作业的运行。

3虚拟内存是操作系统发展史上的一个革命性突破,这项技术的使用扩充了内存的容量,呈现在程序员和用户面前的是比实际容量大得多内存,使得计算机能够运行更多更大的程序,甚至是一个比内存容量还要大的程序。

不同的操作系统环境采用不同的内存管理方法,常用的内存管理方式有这几种:单一连续分区存储管理、固定分区存储管理、可变分区存储管理、分页式存储管理、分段式存储管理。

单一连续分区管理
单一连续内存管理方式是最早出现和最简单的一种内存管理方式,仅适用于单用户、单任务操作系统中,而不能用于多用户系统或单用户多任务系统。

4例如早期的MS-DOS系统就采用这种管理模式。

在单用户单任务的系统下,内存中只有两个程序:操作系统和一个用户程序。

整个内存被分成系统区域和用户区域两个部分,系统区域提供给操作系统适用,用户区域提供给程序适用。

根据操作系统在内存中的位置,单一连续分区管理有三种组织方案,下图中图(a)所示为操作系统位于内存低地址部分的随机存储器(RAM)中;图(b)所示为操作系统位于内存高地址部分的只读存储器(ROM)中;图(c)所示为设备驱动程序位于内存最高段中的ROM中而操作系统其余部分位于RAM的低地址部分。

0xffff 0xffff 0xffff 5
3引自《操作系统》第125页,许曰滨、刘英华编著,北京邮电大学出版社出版。

4引自《操作系统原理与实践》第130页,邹鹏、阳国贵编著,高等教育出版社出版。

5引自《操作系统实用教程》第172页,范立南、刘飒编著,北京大学出版社出版。

(a) (b) (c)
在这种单用户单任务的系统中,内存里只有操作系统和一个用户程序,而操作系统所占用的内存空间是恒定的,从而我们可以将用户程序总是加载到同一个内存地址上。

由于这个关系的存在,当用户程序装入内存时,所有物理地址与虚地址之间都存在一个固定的逻辑关系:物理地址=虚地址+程序在内存的起始地址。

这样,用户程序里面的地址都可以事先算出来,即在程序运行之前就能计算出所有物理地址。

当用户程序被装入内存时,由装入程序一次性把逻辑地址转换为换成物理地址,从而达到内存管理的一个基本功能要求——内存地址映射。

这种地址映射的方法成为静态地址映射。

单一连续分区管理的内存保护很容易实现:对于上图(a)中的情况,只要规定CPU产生的每个访问内存的地址addr>m;对于图(b)中的情况,只要规定CPU 产生的每个访问内存的地址addr<m;对于图(c)中的情况,只要规定CPU产生的每个访问内存的地址m<addr<n。

一旦上述条件不满足,就产生地址越界错误,终止程序的执行即可。

单一连续分区管理的优点是管理简单,要求硬件支持少。

但是存在较多的缺点:
(1)由于每次只能有一个作业进入内存,故它不适用于多道程序设计,整个系统的工作效率不高,资源利用率低下。

(2)只要作业比用户区小,那么在用户区里就会形成碎片,造成内存储器资源的浪费。

如果用户作业很小,那么这种浪费是巨大的。

(3) 若用户作业的相对地址空间比用户区大,那么该作业就无法运行。

即大作业无法再小内存上运行。

6
固定分区存储管理
随着计算机技术的发展和内存容量的增加,为了提高资源的利用效率,系统具有“多道”的模式,单一连续分区的管理模式不再适用。

在这种情况下的内存管理最容易让人想到的就是将内存分成若干个连续的分区,在每一个分区中装入不同作业,从而实现多个程序的同时运行。

6 引自《操作系统教程》第44页,宗大华、宗涛编著,人民邮电出版社出版
划分分区的办法可以有两种:分区大小相等和分区大小不等。

分区大小相等的划分方案管理简单,但是缺乏灵活性,当程序太小时内存空间浪费严重,当程序太大时无法装入内存。

所以一般采用分区不等的划分方案,根据程序大小的统计规律,把内存区划分为含有多个较小的分区、适量中等分区以及少量的大分区的形式。

当有一个进程要求进入内存时,选择一个合适的空闲分区(满足进程要求空间的最小分区)分给进程;没有合适的空闲分区时则让其等待。

为了充分利用存储器,将进程按照请求空间的大小在不同的分区排队等待,如图下(a )。

这种方法管理简单,但有可能出现大分区队列空闲而小分区队列拥挤的现象。

当这种情况出现时,会使存储器造成更大的浪费。

为充分利用存储器,系统只维持一个存储器等待队列,如下图(b )。

任何时候,只要有一个分区变为空闲,队列中的一个进程就可装入运行。

7
为了记录每个分区的大小、其实地址、分配与否等信息,需要建立一个分区说明表,如下表所示。

当程序要装入时,由内存分配程序负责检索该表,并从表中选择一个最合适的,又尚未分配的分区分配给该进程,然后将表中分配状态进行修改;若找不到适合的分区,则拒绝为其分配内存,让其继续等待。

固定分区这种管理方法,由于程序可以加载到内存的多个地方,加载后的地
7 引自《操作系统原理教程》第74页,张丽芬、刘美华编著,电子工艺出版社出版。

(a) (b)
址是不固定的,所以在进行地址翻译时静态地址映射的方法将不再适用。

我们看到,一个程序是加载到内存里事先划分好的某片区域,而起该程序是整个加载进去。

该地址只要加上其所占区域的起始地址即可获得物理地址。

8即物理地址=虚拟地址+程序所在区域的起始地址。

物理地址的确定不再是装入内存时就全部转换为物理地址,而是在CPU执行每一条指令时进行地址转换,称为动态地址映射。

对于内存保护,由于每个程序占用连续的一片内存空间,因此只要其访问的空间不超出该片区域则为合法的访问。

可以用两个寄存器记录程序的基址和长度,程序发出的地址如果大于程序长度即为非法访问,如果小于程序长度就用基址加上便宜获得其物理地址。

固定分区存储管理使多道编程得到实现,调高了处理器的利用率。

但是内存利用效率仍然较低,且调入作业受到分区大小的严格限制,因此仅适合于进程的大小及数量事先能够预知的系统中。

可变分区存储管理
为了克服固定分区的弊端,进一步挺高内存利用率,避免有足够内存空间而不能装入作业的问题,产生可变分区存储管理方案。

可变分区是指在进程装入内存时,把可用的内存空间“切出”一个连续的区域分配给进程,以适应进程大小的需求。

整个内存分区的大小和分区的个数不是固定不变的,而是根据装入进程的大小动态地划分,因此也被称为动态分区。

9在这种内存管理模式下,系统刚启动尚无用户程序装入内存之前,整个用户区为一个大的空闲分区。

伴随用户程序的载入、执行和退出,用户区被划分成若干分区,有的分区被用户程序占用,有的分区保持空闲。

当一个程序试图载入内存时,操作系统为其寻找一个足够大的空闲分区,并将该分区一分为二,一部分分配给用户程序,另一部分保留下来并形成一个较小的空闲分区。

当一个程序运行结束退出内存时,若其归还的内存空间与其他空闲分区相邻接,则两个空闲分区合并成一个大的空闲分区,方便大的用户程序装入。

为了实现可变分区的内存分配,系统必须记录查找内存目前的使用情况,常
8 引自《计算机的心智:操作系统之哲学理解》第145页,邹恒明编著,机械工业出版社出版。

9 引自《计算机操作系统》第114页,郁红英、李春强编著,清华大学出版社出版。

用的数据结构有两种:空闲分区表和空闲分区链。

采用空闲分区表的数据结构时,为每个尚未分配使用的分区在分区表中设置一段记录,包括分区序号、分区其实地址和分区大小,如下图(a)。

采用空闲分区链时,需要在每个空闲分区中设置用于控制分区分配的信息以及指向下一个空闲分区的指针,方便系统对空闲分区进行遍历和查找,如下图(b)。

分区表的方法管理简单,而分区链的方法不需要为了记录空闲分区信息而分配额外的内存空间。

(a) (b)
当调度一个程序进入内存时,可能有多个可用分区都能满足该作业的需求,这时就有一个应该把那个分区分配给程序的问题。

可采用的算法有以下4种:首次适应法:每次进行内存分配时,系统根据申请空间的大小,从头到尾扫描分空闲区表(或链),一旦找到一个空间大于或等于申请空间的分区就立即将该分区分配给进程。

这种算法的特点是优利用内存低地址端,高地址端有大空闲区;缺点是容易造成低端地址部分不断被划分,形成很多难以利用的碎片,同时,每次查找都是从低址部分开始的,增加系统开销,查找效率比较低。

10循环适应法:每次存储分配总是从上次分配的位置开始向尾部查找,仍然将找到的第一个满足要求的分区分配给进程。

这种算法改善了首次适应法“优利用内存低地址端,高地址端有大空闲区”这种内存负载不均衡的问题,并且能够有效提高命中率,减少查找分区时的开销,碎片也可能得到减少。

最佳适应法:在内存分配时,从空闲分区表(或链)中找到一块能满足进程需求的最小空间分配给它。

这种算法减少了将大空闲区进行多次分割造成的空间浪费,但是容易形成一些很小的碎片无法使用,而且每次分配都要从头到尾进行搜索,增大系统开销。

为了减小这一开销,一个有效的方法是将空闲分区按照空间尺寸排序,每次分配时查找到的第一个满足条件的分区即为最佳适应分区。

最坏适应法:每次进行分配时从空闲分区中寻找一个最大分区进行分配。

这10 引自《计算机操作系统》第90页,冯裕忠、方智、周舫编著,清华大学出版社出版。

样能够使得剩下来的空闲分区不至于太小,还能进行利用,减少外部碎片引起的浪费,但是对大作业的运行是不利的。

可变分区存储管理方案由于可能对一块连续的内存进行多次的分割,容易产生很多较小的难以利用的分区,造成磁盘碎片,降低磁盘利用率。

为了解决这些问题,可以采用可重定位分区分配:一旦出现分散的空白区,就将空白区集中,从而移动内存中的作业,由存储器管理实施重定位,把已分配的各个分区“移动”仅靠一边,将空白区集中到另一端。

11
上述的三种内存管理方法(单一连续分区、固定分区和可变分区)都是将进程的全部信息一次装入一个连续的主分区直至运行结束。

这就产生了一个问题:当进程的大小大于内存可用分区(或空间)时,程序将无法运行。

这就限制了在计算机上开发较大程序的可能。

为了解决这些问题,人们找到了覆盖和交换的两种技术。

覆盖:同一内存区可被一个或多个进程的不同程序段重复使用。

通常一个进程有多个在功能上相互独立的程序段。

在这些程序段中,当一个程序段在运行,则其他程序段不会同时运行。

利用这个事实,可以让这些程序段共用一个内存区,用到哪段程序段就将该段程序段载入内存,这个共享的内存区就成为覆盖区,相互覆盖的程序段称为覆盖段。

交换:系统根据需要把主存中暂时不运行的某个(或某些)部分或全部信息移到外存,而把外存中的某个(或某些)进程移到相应的主存区,并使其投入运行。

12通过这种反复的在内存出入的技术,实现了在小容量内存里运行多个用户进程。

尽管分区管理的方式比较简单,但是存在程序大小受到限制,内存碎片多,利用率不高等问题,内存拼接系统开销大,不利于内存共享等诸多问题。

产生这些问题的根源是进程需要加载到一个连续的内存空间中,如果将其连续性要求出去,上述问题将得到很大改善,由此出现了分页式存储管理和分段式存储管理。

11 引自《计算机操作系统实用教程》第89页,王旭启、郝占军编著,北京理工大学出版社出版。

12 引自《操作系统原理教程》第79页,张丽芬、刘美华编著,电子工业出版社出版。

分页式存储管理
分页存储管理,是将一个进程的逻辑地址空间分成若干个大小相等的部分,每一部分成为一个页面或页。

为各页编号,叫做页号。

页号从0开始,如第0页、第1页等。

相应的,把内存空间也划分成与页面相同大小的若干个存储块,称为物理块、页框或物理页面。

也同样为各块编号,仍然从0开始,如第0块,第1块等。

13
在进行内存分配时以页面为单位进行分配,一个程序的一个页面可以存放在任意一个物理页面里,无需连续存放;程序运行时也无需将整个程序加载到内存,而只加载运行用到的几个页面,在程序运行过程中如果还需要其他页面就产生缺页中断,再将该页面调入内存。

在分页系统下,一个程序发出的虚拟地址由两部分组成:页面号和页内偏移值,如下图所示:
对于一个32位的系统,如果其中0~11位是页内偏移值,则每页的大小为4KB ;12~31为页号,地址空间最多允许有1M 个页。

由于进程的若干个页被离散低存储在内存的多个存储块中,为了能够找到每个页所对应的存储块,系统为每个进程建立了一张页表。

表中记录了相应页在内存中对应的物理块号。

再进行内存访问时,先从虚地址中得到页面号,根据这个页面号到页表中进行查找,得到该页面号在内存中的物理块号,根据物理块号找到首地址后在由业内偏移值得到物理地址。

过程如下图所示:
如果根据虚拟地址中的页面号没有在页表中找到相应的信息,说明该页面并
13 引自《计算机操作系统实用教程》第90页,王旭启、郝占军编著,北京理工大学出版社出版。

内存 址空间 进程页表
1 2 3 4 0
没有载入到内存中,此时将产生一个缺页中断,并将虚页从磁盘载入到内存中,之后再进行访问。

分页系统虽然有较多的优势,比如消除了内存外碎片,内存内碎片少,内存利用率高,实现地址扩充,程序大小受内存限制小等,但是其也有自己的不足,一个最大的问题就是页表很大,本身占用较大的内存空间。

为了减小页表体积,可以采用多级页表的办法。

比如采用两级页表,则将虚拟地址分成三个部分,如下图:
先根据前10为的值找到顶级页表的对应记录,得到所需的次级页表;再根据中间的10为找到次级页表的对应记录,得到对应的物理页面号,物理页面号与业内偏移值和起来得到最后的物理地址。

一个程序在运行时,其顶级列表常驻内存,而次级页表则根据需要可能存放在内存中,也可能在磁盘中,但大部分次级列表都在磁盘中,这样就极大地减小了内存的占用。

内存占用虽然减小了,但是同时增加了系统开销。

对于二级页表,一次内存访问变成了三次内存访问。

如果次级页表不再内存,那么还要产生缺页中断,增加一次磁盘访问。

对于更多级页表,内存访问速度影响将会更加明显。

分页系统的另外一个缺点就是可能发生内存抖动。

由于内存中的页面总在进行替换,如果更换掉的页面是一个很快就会被再次访问的页面,那么在此次缺页中断之后很快又会产生新的缺页中断,最坏的情况就是每次内存访问都产生缺页中断。

由于磁盘访问速度相比内存慢得多,所以系统的运行效率急剧下降。

还有一点不足是共享困难。

虽然理论上我们可以按页共享,但是这根本无法实现,因为一个页面的内容可能既包括共享的数据也包含不能共享的数据。

只要该页面中包含一条不能共享的地址,这个页面就不能共享。

分段式存储管理
分段式存储是离散分配的另外一种方案。

其管理方案与分页式管理有一定的相似性。

分段式存储管理方案中,将进程对应程序和数据按照其本身的特性成分若干个段,每个段定义了一组有意义的逻辑信息单位。

如主程序段MIAN、子程序段
SUB、数据段DATA等。

每个段有自己的名字,每个段从0开始编址,段的长度由相应逻辑信息单位的长度决定。

在内存中,每个段占用一段连续的分区。

14由于分成多个段,进程的地址空间是二维的,包含段号和段内地址,如下图:
与分页式内存管理相似,系统为每个进程建立一张段表,段表中记录着段号、该段在内存中的起始地址和段的长度,还可以包含一个存取控制块,如下图:
进行内存访问时,系统根据段号查找页表,得到该段的起始地址,并将段内偏移地址与段长进行比较,如果偏移地址大于段长,则产生一个越界中断;如果访问没有越界,则由起始地址和段内偏移地址相加得到最后的物理地址。

分段和分页的区别主要在于三个方面:
(1)页是信息的物理单位,是按照大小硬性进行划分的;段是信息的逻辑单位,是根据逻辑进行认为主动划分的,具有完整的意义;
(2)页的大小事固定的,段的大小是由用户编写的程序决定;
(3)页的逻辑地址是一维的,段的逻辑地址是二维的。

分段存储方式的引入,由于其与人们编程时的行为一致,给编程带来方便;由于程序和数据的共享往往是以信息的逻辑单位为基础的,所以利用数据和代码的分段共享和分段保护。

鉴于分页式内存管理和分段式内存管理各有优劣,而且存在优势互补,通常将两种管理方式结合起来成为段页式内存管理。

使其即能像分段内存管理方式那样便于实现信息共享、信息保护、动态链接并较好地满足用户多方面的需要,又能像分页内存管理系统那样很好地解决内存外部碎片的问题以及为个分段离散地分配内存等问题,从而能有效提高内存利用率。

15
14 引自《计算机操作系统》第124页,郁红英、李春强编著,清华大学出版社出版。

15 引自《操作系统原理与实践》第158页,邹鹏、阳国贵编著,高等教育出版社出版。

相关文档
最新文档