第二章-存储管理

1.逻辑地址和物理地址

 物理地址: 加载到内存地址寄存器中的地址,内存单元的真正地址。

 逻辑地址: 源程序经汇编或编译后得到的是目标代码程序(装入模块),由于编译程序无法确定目标代码在执行时所驻留的实际内存地址,故一般总是从零号单元         开始为其编址,并顺序分配所有的符号名所对应的地址单元。由于目标代码中所有的地址值都相对于以"0"为起始的地址,而不是真实的地址,故称         这类地址为相对地址,逻辑地址或虚拟地址。

当装入程序将可执行代码装入内存时,程序的逻辑地址与程序在内存的物理地址一般是不同的,必须通过地址转换将逻辑地址转换成内存地址,这个过程称之为地址重定位。如下图描述

 

内部碎片:分配给某进程的内存区域中,有些部分没有用上。

外部碎片:  是指内存中的某些空闲分区由于太小而难以利用。

 

 

 

2.地址定位方式

  •   绝对装入(固定定位方式)

    在编译时,如果知道程序将放到内存中的哪个位置,编译程序将产生包含绝对地址的目标代码。

    装入程序按照装入模块中的地址,将程序和数据装入内存。

   例:如果知道装入模块要从地址为100的地方开始存放,那么编译,链接后得到的装入模块的指令直接就使用了绝对地址。

  •  静态重定位(可重定位装入)

       编译,链接后的装入模块的地址都是从0开始的,指令中存放的地址都是逻辑地址。可根据内存的当前情况,将装入模块装入到内存合适的位置。

    装入时对地址进行"重定位",将逻辑地址变换为物理地址(地址变换是在装入时一次完成的)。

    其特点是在一个作业装入内存时,必须分配其要求的全部内存空间,如果没有足够的内存,就不能装入该作业。

    作业一旦进入内存后,在运行期间就不能再移动,也不能再申请内存空间。

  •  动态重定位(动态运行时装入)

     编译,链接后的装入模块的地址都是从0开始的。装入程序把装入模块装入内存后,并不会立即把逻辑地址转换为物理地址,而是把地址转换推迟到程序               真正要执行时才进行。因此装入内存后所以的地址仍然是逻辑地址。这种方式需要一个重定位寄存器的支持。

     重地位寄存器:存放装入模块存放的起始位置。

     采用这种方式有许多好处:允许程序在内存中发生移动;可将程序分配到不连续的存储区中,......还有几条没写。

3.内存空间的分配与回收

 

 

 

 

 

 

  • 单一连续分配

    在单一连续分配方式中,内存被分为系统区和用户区。系统区用于存放操作系统的相关数据;用户区用于存放用户进程相关数据。

    内存中只能有一道用户程序,用户程序独占整个用户区空间。

   优点:实现简单;无外部碎片

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

  •   固定分区分配

    为了能在内存中装入多道程序,于是将整个用户空间划分为若干个固定大小的分区,在每个分区中只能装入一道作业。

    固定分区分配又可分为两种: 分区大小相等和分区大小不等。

    分区大小相等: 缺乏灵活性,但是很适合用于用一台计算机控制多个相同对象的场合。

    分区大小不等: 增加了灵活性,可以满足不同大小的进程需求。

     优点:实现简单,无外部碎片。

     缺点:会产生内存碎片,内存利用率低。

  • 动态分区分配

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

   动态分区分配没有内部碎片,但是有外部碎片。

4. 动态分区分配算法

  •  首次适应算法

    算法思想:每次都从低地址开始查找,找到第一个能满足大小的空闲分区。

    空闲分区以地址递增次序排列。

    优点:综合看性能最好。算法开销小,回收分区后一般不需要对空闲分区队列重新排序。

  •  最佳适应算法

    算法思想:为了保证当“大进程”到来时能有连续的大片空间,可以尽可能多地留下大片的空闲区,即,优先使用更小的空闲区。

    空闲储存区管理表的组织方法可以采用顺序结构,也可以采用链接结构。

    如采用顺序结构,空闲分区按地址由小到大的顺序登记在表中,分配时在其中挑选一个满足分配大小的最小的分区。

    当采用链式结构时,空闲区可以按递增的顺序排列,但采用这种结构会降低释放算法的效率。

    优点:会有更多的大分区被保留下来,更能满足大进程的需求。

    缺点:会产生很多太小的,难以利用的碎片;算法开销大,回收分区后可能需要对空闲分区队列重新排序。

  •   最差适应算法

    算法思想:和最佳适应算法相反。

    在实施最差适应算法时,空闲区管理表项一般以m_size()由大到小的次序组织成一个链接表,因此查找分割的总是最大的第一个空闲储存区。

    这种做法看起来好像将大木材当柴烧,大布料剪碎做小衣服,但其优点也特别明显,即一次查找就行,一次定输赢,所以该算法的分配速度最快。

    这对实时性要求高的应用领域较为合适。

    采用按存储区大小顺序排列的链表的形式虽然释放一个空闲块时的速度较慢,当分配效率是一切算法中最高的。

    优点:可以减少难以利用的小碎片。

    缺点:大分区容易被用完,不利于大进程;同样和最佳适应算法一样算法开销大。

5.内存扩充技术

  内存扩充技术就是借助大容量的辅存在逻辑上实现内存的扩充,以解决内存容量不足的问题。

  •    覆盖技术

    覆盖技术就是将一个大程序按程序的逻辑结构划分成若干个程序(或数据)段,并将不会同时执行,从而不必同时装入内存的程序段分在一组内,该组称                   为覆盖段。

  

 

 

 

 

 

 

 

 

  可以看出,采用覆盖技术后总共只需要80KB内存。这种覆盖管理技术采用的是静态储存分配和静态重定位方式。

  如果采用动态重定位的系统中运行,事先不必划分或指定覆盖区,在执行中调用模块时才由覆盖管理程序决定装入地址,这样总共只需要70KB

  内存就可以运行该左右。

  覆盖对程序员是不透明的。增加了程序员的负担。

  •   交换技术

  交换技术就是把暂时不用的某个程序及数据部分或全部从内存移到外存中去,以便腾出必要的内存空间,或把制定的程序或数据从外存读到相应的内存中,         并将控制权转给它,让其在系统上运行的一种内存扩充技术。

 

 

 

 

 

 

 

 

  如图所示,阴影区域表示未使用的内存。开始时内存中只有进程A。之后创建进程B和C或者从磁盘将它们还如内存。d图显示A被交换到磁盘,D被调入到             内存,然后B被调出,A再次被调入。

  •   虚拟技术

       虚拟储存器基于局部性原理,在不将所有程序内容装入内存的情况下,仅调入程序开始执行所需的部分内容即启动程序,其余内容仍然驻留外存;

   当程序所需要的内容不在内存上时,就发出中断请求,由系统将其调入内存;如果此时内存已满,则由系统根据某种算法换出一部分内容空间上的内容,            从而接纳新调入的指令和数据;这样就解决了常规存储器管理方式不易处理的两个问题。

  虚拟储存器的实现方式:

      ①分页请求系统:在分页系统的基础上增加请求调入和页面置换功能所形成的虚拟储存系统。系统需要提供必要的硬件和软件来支持请求分页的实现。

      ②分段请求系统:在分段系统的基础上增加请求调入和页面置换功能所形成的虚拟储存系统。系统需要提供必要的硬件和软件来支持请求分页的实现。

 

4.非连续的分配的储存管理方式(分页和分段)

  前面介绍的储存管理系统中,作业在主存要占用一个连续的存储区,如果将一个作业用户空间划分成为较小的单位,这些单位可以分散的驻留到内存的“碎片”中,这样就能充分地利用“边角料”,提高主存的利用率。

  页式存储管理的基本思想是把作业的虚地址空间划分成若干长度相等的页(page),也称为虚页,每个作业的虚页都从0开始编号。

  主存也划分成若干与虚页长度相等的页架(frame),也称为页框或实页。程序装入时,每个虚页装到主存中的一个页架中,这些页架可以是不连续的。

  页式存储管理又可以分为两类。

  •  纯页式(静态页式)存储管理

    要求一个作业在运行前将所有的虚页都装入主存的页架中。

  •    请求页式(动态页式)存储管理

    运行一个作业时,不必将所有的虚页都装入主存的页架中,只要装入当前运行时所必须访问的若干页,其余虚页仍驻在辅存中。

  

  

 

 

     虚拟地址的页内偏移部分占据低n个二进制位,使得2n刚好等于页的大小。

  程序的虚拟地址空间是连续的,但程序的虚页可以分配到内存中不连续的空闲页架中,故分页系统需要在主存中开辟一个页表区域,来建立每个作业的虚号页(page index)到内存的页架号(frame index)之间的映射关系。

 

纯分页系统的地址变换如上图

在程序执行时,对于每条访问内存的指令,纯分页系统地址变换过程如下(由硬件自动完成)。

首先,将逻辑地址拆分为两部分,页号 + 页内地址

然后去找到页表,去其中找到与页号对于的物理块,在找之前,对页号和页表项进行比较,判断一波,看页号是不是越界了。

若大于,则表示本次所访问的地址已超越进程的地址空间。于是,这一错误将被系统发现并产生一地址越界中断。

若未越界,则将页表在内存中的开始地址作为起始地址,加上表项的增量,(即  页号  ×  每个表项所占的内存大小),便来到了存放有该页号在页表中对应的表项的位置,取出其中的内容(对应的块号),便可获得实际的物理块号。再加上之前的页内偏移地址,便可以得到其物理地址。

  • 快表和慢表

  直接采用上述机构进行地址变换实际上是不可取的。由于页表是驻留在主存中的,为了进行地址变换,对于每条访问内存的指令,系统至少访问内存两次            (第一次查找页表,第二次真正访问指令或数据),这样的效率是难以容忍的。

  为了克服这个缺点,很对页式系统都配有一组快速寄存器,用来存放当前运行作业的页表表项,以加速地址变换过程,这种页表称之为块表。主存中的页    表有时也称为慢表。

  块表的引入极大地提高了地址的变换速度。

5.页面淘汰(置换)算法

  •   最佳置换算法(OPT)

     从主存中移出永远不再需要的页面;如无这样的页面存在,则选择最长时间不需要访问的页面。于所选择的被淘汰页面将是以后永不使用的,或者是在最长时间内不再被访问的页面,这样可以保证获得最低的缺页率。最优算法是无法实现的,但可以作为理论上的评价标准,用以鉴别其他的淘汰算法。

  •   先进先出置换算法(FIFO)

     最简单的页面置换算法。这种算法的基本思想是:当需要淘汰一个页面时,总是选择驻留主存时间最长的页面进行淘汰,即先进入主存的页面先淘汰。其理由是:最早调入主存的页面不再被使用的可能性最大。 

     FIFO算法还会产生当所分配的物理块数增大而页故障数不减反增的异常现象,这是由 Belady于1969年发现,故称为Belady异常,如图3-28所示。只有FIFO算法可能出现Belady 异常,而LRU和OPT算法永远不会出现Belady异常。  

      FIFO算法只是在作业是按顺序访问地址空间的情况下才是理想的,否则效率不高,因为该算法很可能淘汰的是经常要访问的页。实际系统很少用。

  •   最近最久未使用(LRU)算法

      这种算法的基本思想是:利用局部性原理,根据一个作业在执行过程中过去的页面访问历史来推测未来的行为。它认为过去一段时间里不曾被访问过的页面,在最近的将来可能也不会再被访问。所以,这种算法的实质是:当需要淘汰一个页面时,总是选择在最近一段时间内最久不用的页面予以淘汰。

      LRU性能较好,但需要寄存器和栈的硬件支持。LRU是堆栈类的算法。理论上可以证明,堆栈类算法不可能出现Belady异常。FIFO算法基于队列实现,不是堆栈类算法。这种算法的时间主要耗在大量的比较上。

      其他各种算法: https://www.cnblogs.com/kkkkkk/p/5524208.html(包含全局置换算法)。

分段方式:

      https://blog.csdn.net/qwe6112071/article/details/70500258

posted @ 2019-03-27 21:24  小新猩  阅读(475)  评论(0编辑  收藏  举报