操作系统内存管理
发布日期:2021-06-29 17:21:11 浏览次数:2 分类:技术文章

本文共 7292 字,大约阅读时间需要 24 分钟。

目录

         

         


 

知识框架

 

一、内存管理

1. 内存管理相关概念

内存管理是指操作系统将内存空间进行合理划分和有效地动态分配。具体功能包括:

  • 内存空间的分配与回收:由操作系统完成主存储器空间的分配与管理,使程序员摆脱存储分配的麻烦,提高编程效率。
  • 地址转换:在多道程序环境下,程序中的逻辑地址内存中的物理地址不一致,因此存储管理需要提供地址变换功能,把逻辑地址转换成相应的物理地址。
  • 内存空间的扩充:利用虚拟存储技术自动覆盖技术,从逻辑上扩充内存。
  • 存储保护:保证各道作业在各自的存储空间内运行,互不干扰。

 

1.1 进程运行的基本原理和要求

创建进程首先要将程序和数据装入内存,将用户源程序变为可在内存中执行的程序,通常需要以下几个步骤:

  • 编译:由编译程序将用户源代码编译成若干个目标模块。
  • 链接:由链接程序将编译后形成的一组目标模块,以及所需的库函数链接在一起,形成一个完整的装入模块。
  • 装入:由装入程序将装入模块装入内存运行。

这三步过程如图1-1所示:

                                    图1-1 对用户程序的处理步骤

 

程序的链接有以下三种方式:

  • 静态链接:在程序运行之前,先将各目标模块及它们所需的库函数链接成一个完整的可执行程序,以后不再拆开。
  • 装入时动态链接:将用户源程序编译后所得到的一组目标模块,在装入内存时,采用边装入边链接的链接方式。
  • 运行时动态链接:对某些目标模块的链接,是在程序执行中需要该目标模块时,才对它进行链接。

 

1.2 逻辑地址空间与物理地址空间

逻辑地址空间:编译后,每个目标模块都是从0号单元开始编址,称为该目标模块的逻辑地址(也称相对地址)。当链接程序将各个模块链接成一个完整的可执行目标程序时,链接程序顺序依次按各个模块的相对地址构成统一的从0号单元开始编址的逻辑地址空间

物理地址空间:物理地址空间是指内存中物理单元的集合,它是地址转换的最终地址,进程在运行时执行指令和访问数据最后都要通过物理地址从主存中存取。当装入程序将可执行代码装入内存时,必须通过地址转换将逻辑地址转换成物理地址,这个过程称为地址重定位

 

2. 覆盖与交换

覆盖与交换技术是在多道程序环境下用来扩充内存的两种方法。

2.1 覆盖

早期的计算机系统中,主存容量很小,放不下用户进程的现象经常发生,覆盖技术就是用来解决这个问题的。

 

覆盖的基本思想是:由于程序运行时并非任何时候都要访问程序及数据的各个部分,因此可以把用户空间分成一个固定区若干个覆盖区。将经常活跃的部分放在固定区,其余部分按调用关系分段,首先将那些即将要访问的段放入覆盖区,其他段放入外存中,在需要调用前再将其调入覆盖区,替换覆盖区中原有的段。

 

特点:打破了必须将一个进程的全部信息装入主存后才能运行的限制。

缺点:① 当同时运行程序的代码量大于主存中仍无法实现;② 内存中能够更新的地方只有覆盖区,不在覆盖区的段会常驻内存。

 

2.2 交换

交换的基本思想是:把处于等待状态的程序从内存移到辅存,把内存空间腾出来,这一过程又叫换出;把准备好竞争CPU运行的程序从辅存移到内存,这一过程又叫换入

 

例如,有一个CPU采用时间片轮转调度算法的多道程序环境,时间片到,内存管理器将刚刚执行过的进程换出,将另一进程换入到刚刚释放的内存空间中。理想情况下,内存管理器的交换速度足够快,则可以保证总有进程在内存中可以执行。

 

2.3 覆盖技术与交换技术的比较

交换技术主要是在不同进程之间进行,而覆盖则用于同一个程序或进程中。由于覆盖技术要求给出程序段之间的覆盖结构,使得其对用户和程序员不透明,所以对于主存无法存放用户程序的问题,现代操作系统是通过虚拟内存技术来解决的,覆盖技术已成为历史;而交换技术在现代操作系统中仍有较强的生命力。

 

3. 连续分配管理方式

连续分配和非连续分配是内存分配的两种方式。连续分配方式是指为一个用户程序分配一个连续的内存空间,比如某用户需要1GB的内存空间,它就在内存空间中分配一块连续的1GB的空间给用户。连续分配又可以分为单一连续分配固定分区分配动态分区分配三种方式。

 

内存分配可能造成的空间浪费称为碎片,又可分为内部碎片外部碎片

  • 内部碎片:分区内部的空间浪费。
  • 外部碎片:所有内存分区外的存储空间造成的空间浪费。

 

3.1 单一连续分配

内存在此方式下分为系统区用户区系统区仅提供给操作系统使用,通常在低地址部分用户区为用户提供的、除系统区之外的内存空间。这种方式无需进行内存保护,因为内存中永远只有一道程序,肯定不会因为访问越界而干扰其他程序。

 

优点:简单,无外部碎片,可以采用覆盖技术,不需要额外的技术支持。

缺点:① 只能用于单用户、单任务的操作系统中;② 有内部碎片,存储器利用率低。

 

3.2 固定分区分配

固定分区分配是最简单的一种多道程序存储管理方式,它将用户内存空间划分为若干个固定大小的区域,每个分区只装入一道作业。当有空闲分区时,便可以再从外存的后备作业队列中选择适当大小的作业装入该分区,如此循环。

 

划分分区时有两种不同的方法(如图3-1所示):

  • 分区大小相等:用于利用一台计算机去控制多个相同对象的场合,缺乏灵活性。
  • 分区大小不等:划分为含有多个较小的分区、适量的中等分区及少量的大分区。

  

                                         

                                                        图3-1 划分分区的两种方式

 

优点:无外部碎片。

缺点:① 程序可能太大而放不进任何一个分区中,这时候需要用覆盖技术来使用内存;② 主存利用率低,因为程序小于固定分区大小时,也占用了一个完整的分区,这样分区内部空间浪费,这种现象称为内部碎片

 

说明:固定分区分配很少用于现在通用的操作系统中,但在某些用于控制多个相同对象的控制系统中仍发挥着一定作用。

 

3.3 动态分区分配

动态分区分配又称可变分区分配,是一种动态划分内存的分区方法。这种方法不预先将内存划分,而是在进程装入内存时,根据进程的大小动态地建立分区,并使分区的大小正好适合进程的需要。因此系统中分区的大小和数目是可变的。

 

在进程装入或换入主存时,如果内存中有多个足够大的空闲块,操作系统必须确定分配哪个内存块给进程使用,这就是动态分区的分配策略,主要有以下几种算法:

  • 首次适应(First Fit)算法:空闲分区以地址递增的次序链接。分配内存时顺序查找,找到大小能满足要求的第一个空闲分区。
  • 最佳适应(Best Fit)算法:空闲分区按容量递增的次序链接,找到第一个能满足要求的空闲分区。
  • 最坏适应(Worst Fit)算法:又称最大适应(Largest Fit)算法,空闲分区按容量递减的次序链接,找到第一个能满足要求的空闲分区,也就是最大的分区。
  • 邻近适应(Next Fit)算法:又称循环首次适应算法,由首次适应算法演变而成,不同之处是分配内存时从上次查找结束的位置开始继续查找

上述四种算法中,首次适应算法不仅是最简单的,通常也是最好最快的。

 

缺点:动态分区在开始分配时是比较理想的,但是之后会导致内存中出现许多小的内存块。随着时间推移,内存中会产生越来越多的碎片,称为外部碎片,指在所有分区外的存储空间,这与固定分区中内部碎片正好相对。解决外部碎片可以通过紧凑技术,就是操作系统不时地对进程进行移动和整理。但是这需要动态重定位寄存器的支持,且相对费时

 

4. 非连续分配管理方式

非连续分配允许一个程序分散地装入到不相邻的内存分区中。这也需要额外的空间存储分散区域的索引。

 

非连续分配管理方式根据分区的大小是否固定分为分页存储管理方式分段存储管理方式分页存储管理方式又根据运行作业时是否要把作业的所有页面都装入内存才能运行分为基本分页存储管理方式和请求分页存储管理方式。

 

4.1 基本分页存储管理方式

固定分区会产生内部碎片动态分区会产生外部碎片,这两种技术对内存的利用率都比较低。我们希望内存的使用能尽量避免碎片的产生,这就引入了分页的思想:把主存空间划分为大小相等且固定的块,块相对较小,作为主存的基本单位。每个进程也以块为单位进行划分,进程在执行时,以块为单位逐个申请主存中的块空间。

 

分页的方法从形式上看类似于分区相等的固定分区方法,但实际上二者有本质的不同:块的大小相对于分区来说小很多,而且进程也按照块进行了划分,进程运行时又按块申请可用空间,这样,进程只会在为最后一个不完整的块申请一个空间时才产生碎片,所以尽管也会产生内部碎片,但是这种碎片相对于进程来说也是很小的,每个进程平均只产生半个块大小的内部碎片(这里也称页内碎片)。

 

(1)分页存储的几个概念:

① 页和页的大小(页也称页面):

进程中的块称为内存中的块称为页框外存也以同样的单位进行划分,直接称为进程在执行时需要申请主存空间就是为每个页分配主存中的可用页框,这就产生了页和页框的一一对应,并且这些页框不必连续,从而实现了离散分配。为方便地址转换,页的大小应该是2的整数次幂。同时页的大小应该适中,如果页太小,会使进程的页数过多,从而导致进程的页表过长,占用内存,还会降低页面换入换出的效率;如果页太大,虽然可以减少页表的长度,提高页面换入换出的效率,但会使页内碎片增大,降低内存利用率。通常,页的大小在1KB ~ 8KB左右。

② 逻辑地址结构:

分页存储管理的逻辑地址结构如图4-1所示:

                                                        

                                                                                图4-1 分页存储管理的逻辑地址结构

逻辑地址结构包含两部分:前一部分页号P后一部分页内偏移量W。地址长度为32位,其中 0 ~ 11位为页内地址,即每页大小为4KB;12 ~ 31位为页号,地址空间最多允许有2^20页。

③ 页表:

为了便于在内存中找到进程的每个页所对应的物理块,系统为每个进程建立了一张页表,记录页在内存中对应的物理块号。页表一般存放在内存中。

页表是由页表项组成的,页表项与分页存储的逻辑地址结构类似,都是由两部分构成的,且第一部分都是页号,但页表项第二部分是物理内存中的块号,而地址的第二部分是页内偏移量;页表项的第二部分(物理块号)地址的第二部分(页内偏移量)共同组成了物理地址

在配置了页表后,进程执行时,通过查找该表 ,即可找到每个页在内存中的物理块号。可见,页表的作用实现从页号到物理块号的地址映射,如图4-2所示。

                                                

                                                                                                    图4-2 页表的作用

 

(2)基本地址变换机构

地址变换机构的任务是将逻辑地址转换为内存中的物理地址,地址变换是借助页表实现的,整个变换过程均由硬件自动完成。

 

(3)分页存储管理方式存在的两个主要问题:

① 每次访存操作都需要进行逻辑地址到物理地址的转换,地址转换过程必须足够快,否则访存速度会降低;

② 每个进程都引入了页表,但是页表不能太大,否则内存利用率会降低。

 

(4)具有快表的地址变换机构

由上面介绍的地址变换过程可知,若页表全部放在内存中,则存取一个数据或一条指令至少要访问两次内存:一次是访问页表,确定所存取的数据或指令的物理地址,第二次根据该物理地址存取数据或指令。显然,这种方法效率较慢。因此,在地址变换机构中增设了一个具有并行查找能力的高速缓冲存储器——快表,用来存放当前访问的若干页表项,以加速地址变换的过程。与之对应的,主存中的页表也常称为慢表。

在具有快表的分页机制中,地址的变换过程为:

① CPU给出逻辑地址后,由硬件进行地址转换并将页号送入高速缓冲存储器,并将此页号与快表中的所有页号进行比较;

② 若找到匹配的页号,说明要访问的页表项在快表中,则直接从中取出该页对应的页框号,与页内偏移量拼接形成物理地址,这样,存取数据只需一次访存;

③ 若没有找到,则需要先访问主存中的页表,在读出页表项后,应同时将其存入快表,以便后面可能再次访问。此时若快表已满,则需要按照一定的算法对旧的页表项进行替换。

 

4.2 基本分段存储管理方式

分页管理方式是从计算机的角度考虑设计的,目的是为了提高内存利用率,且分页通过硬件机制实现,对用户完全透明。而分段管理方式的提出则是考虑了用户和程序员,以满足方便编程、信息保护和共享、动态增长及动态链接等多方面需要。

 

(1)分段:

段式管理方式按照用户进程中的自然段划分逻辑空间,例如,用户进程由主程序、两个子程序、栈和一段数据组成,所以可以把这个用户进程划分为5个段,每段从0开始编址,并分配一段连续的地址空间(段内要求连续、段间不要求连续,因此整个作业的地址空间是二维的)。

 

分段存储的几个概念:

① 逻辑地址结构:

分段存储管理的逻辑地址结构如图4-3所示:

                                                                            

                                                                                            图4-3 分段存储管理的逻辑地址结构

逻辑地址由段号S与段内偏移量W两部分组成。在页式管理中,逻辑地址的页号和页内偏移量对用户是透明的,但在段式管理中,段号和段内偏移量必须由用户显示提供。

 

② 段表:

每个进程都有一张逻辑空间与内存空间映射的段表,其中每一个段表项对应进程的一个段,段表项记录该段在内存中的起始地址和段的长度,如图4-4所示:

                                                                

                                                                                                              图4-4 段表项

在配置了段表后,执行中的进程可以通过查找段表找到每个段所对应的内存区。可见,段表用于实现从逻辑段到物理内存区的映射。

 

4.3 段页式管理方式

段页式管理方式是页式管理方式和段式管理方式的结合。在段页式管理方式中,作业的地址空间首先被划分成若干个逻辑段,每段都有自己的段号,然后再将每一段划分成若干个固定大小的页。对内存空间的管理仍然和分页管理一样,将其分成若干个和页面大小相同的存储块,对内存的分配以存储块为单位。

在段页式管理方式中,作业的逻辑地址分为三部分:段号、页号和页内偏移量。如图4-5所示:

                                                                      

                                                                                     图4-5 段页式存储管理的逻辑地址结构

 

二、虚拟内存管理

1. 虚拟内存概念

1.1 传统存储管理方式的特征

第一部分所讨论的各种内存管理方式都是为了同时将多个进程保存在内存中以便允许多道程序设计,它们都具有下面两个特征:

(1)一次性:作业必须一次性全部装入内存后方能开始运行,这会导致两个问题:① 当作业很大,不能全部装入内存时,该作业便无法运行; ② 当大量作业要求运行时,由于内存不足以容纳所有作业,只能使少数作业先运行。

(2)驻留性:作业被装入内存后,就一直驻留在内存中,其任何部分都不会被换出,直至作业运行结束。运行中的进程,会因为等待I/O而被阻塞,可能处于长期等待状态。

由上述特征可知,许多在程序运行中不用或暂时不用的程序占据了大量的内存空间,而一些需要运行的作业又无法装入运行,显然浪费了宝贵的内存资源。

 

1.2 虚拟存储器的定义和特征

在程序装入时,可以将程序的一部分装入内存,而将其余部分留在外存,就可以启动该程序执行。在程序执行过程中,当所访问的信息不在内存时,由操作系统将所需要的部分调入内存,然后继续执行程序。另一方面,操作系统将内存中暂时不使用的内容换出到外存,从而腾出空间存放将要调入内存的信息。这样,系统好像为用户提供了一个比实际内存大得多的存储器,我们称为虚拟存储器。

之所以称为虚拟存储器,是因为这种存储器实际上并不存在,只是由于系统提供了部分装入、请求调入和置换功能后,给用户的感觉是好像存在一个比实际物理内存大得多的存储器,虚拟存储器的大小由计算机的地址结构决定,并非是内存和外存的简单相加

虚拟存储器有以下三个主要特征:

(1)多次性:指无需在作业运行时一次性全部装入内存,而是允许被分成多次调入内存;

(2)对换性:指无需在作业运行时一直常驻内存,而是允许在作业的运行过程中,进行换进和换出;

(3)虚拟性:指从逻辑上扩充内存的容量,使用户所看到的内存容量远大于实际的内存容量。

 

1.3 虚拟内存技术的实现

虚拟内存中允许将一个作业分多次调入内存,而采用连续分配方式时,会使相当一部分内存空间都处于暂时或“永久”的空闲状态,造成内存资源的严重浪费,也无法从逻辑上扩大内存容量。因此,虚拟内存的实现需要建立在离散分配的内存管理方式的基础上。虚拟内存的实现有以下三种方式:

  • 请求分页存储管理
  • 请求分段存储管理
  • 请求段页式存储管理

 

2. 请求分页管理方式

请求分页管理方式建立在基本分页管理方式的基础上,为了支持虚拟存储器功能而增加了请求调页功能页面置换功能请求分页是目前最常用的一种实现虚拟存储器的方式。

在请求分页方式中,只要求将当前需要的一部分页面装入内存,便可以启动作业运行。在作业执行过程中,当所要访问的页面不在内存中时,再通过调页功能将其调入,同时还可以通过置换功能将暂时不用的页面换出到外存上,以便腾出空间。

 

3. 页面置换算法

进程运行时,若其访问的页面不在内存中需要将其调入,若此时内存中已无空闲空间,就需要从内存中调出一页到外存中。选择调出页面的算法就称为页面置换算法。常见的页面置换算法有以下三种:

(1)最佳置换算法(OPT):

又称为理想置换算法,它每次选择的被淘汰页面将是以后永不使用的,或者是在最长时间内不再被访问的页面,这样可以保证获得最低的缺页率。由于人们目前无法预知进程在内存中的若干页面中哪个是未来最长时间内不再被访问的,因而该算法无法实现。

优点:可以获得最低的缺页率;

缺点:无法预知哪一个页面最长时间不被访问,因此实际上无法实现。

(2)先进先出置换算法(FIFO):

它每次淘汰最早进入内存的页面,也就是在内存中驻留时间最久的页面。该算法实现简单,只需把调入内存的页面根据先后次序链接成队列,设置一个指针始终指向最早的页面即可。

优点:直观,实现简单;

缺点:性能最差,因为一般与页面的使用规则不符。

(3)最近最久未使用置换算法(LRU):

它每次选择最近最长时间未访问过的页面予以淘汰,它认为过去一段时间内未访问过的页面在最近的将来可能也不会被访问。

优点:考虑了程序访问的时间局部性,性能较好,最常用;

缺点:需要较多的硬件支持,硬件成本高。

上述三种算法的具体置换过程可以参考 

LRU算法的代码实现可以参考  和 

 

三、参考

《王道考研系列——操作系统考研复习指导》

 

转载地址:https://blog.csdn.net/m0_37415978/article/details/117259504 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:java文件读取可能出现的两个问题:“系统找不到指定的文件” “拒绝访问”
下一篇:Java异常总结

发表评论

最新留言

能坚持,总会有不一样的收获!
[***.219.124.196]2024年04月21日 00时14分59秒