内存管理

虚拟存储技术

 

当进程运行时,先将其一部分装入内存,另一部分暂留在磁盘,当要执行的命令或访问的数据不在内存中时,由操作系统自动完成将他们从磁盘调入内存的工作。

 

  • 虚拟地址空间——分配给进程的虚拟内存
  • 虚拟地址——在虚拟内存中指令或数据的位置,该位置可以被访问,仿佛他是内存的一部分

 

存储器的层次结构

 

多级存储器结构

 

对于通用计算机而言,存储层次至少应具有三级:最高层为 CPU 寄存器,中间为主存,最底层是辅存

在较高档的计算机中,还可以根据具体的功能分工细划为寄存器、高速缓存、主存储器、磁盘缓存、固定磁盘、可移动存储介质等 6 层。

在存储层次中越往上,存储介质的访问速度越快,价格也越高,相对存储容量也越小。其中,寄存器、高速缓存、主存储器和磁盘缓存均属于操作系统存储管理的管辖范畴,掉电后它们存储的信息不再存在。固定磁盘和可移动存储介质属于设备管理的管辖范畴,它们存储的信息将被长期保存。

在计算机系统存储层次中,寄存器和主存储器又被称为可执行存储器,存放于其中的信息与存放于辅存中的信息相比较而言,计算机所采用的访问机制是不同的,所需耗费的时间也是不同的。

进程可以在很少的时钟周期内使用一条 load 或 store 指令对可执行存储器进行访问,但对辅存的访问则需要通过 I/O 设备来实现。

 

对于不同层次的存储介质,由操作系统进行统一管理:

  • 操作系统的存储管理,负责对可执行存储器的分配、回收以及提供在存储层次间数据移动的管理机制,例如主存与磁盘缓存、高速缓存与主存间的数据移动等。
  • 在设备和文件管理中,根据用户的需求提供对辅存的管理机制。

 

 

主存储器与寄存器

 

主存储器

 

主存储器——用于保存进程运行时的程序和数据。CPU 与外围设备交换的信息一般也依托于主存储器地址空间。由于主存储器的访问速度远低于 CPU 执行指令的速度,为缓和这一矛盾,在计算机系统中引入了寄存器和高速缓存。

 

寄存器

 

寄存器访问速度最快,完全能与 CPU 协调工作,但价格却十分昂贵,因此容量不可能做得很大。寄存器的长度一般以字(word)为单位。寄存器用于加速存储器的访问速度,如用寄存器存放操作数,或用作地址寄存器加快地址转换速度等。

 

 

高速缓存和磁盘缓存

 

高速缓存

 

高速缓存是现代计算机结构中的一个重要部件,其容量大于或远大于寄存器,而比内存约小两到三个数量级左右,访问速度快于主存储器

根据程序执行的局部性原理(即程序在执行时将呈现出局部性规律,在一较短的时间内,程序的执行仅局限于某个部分),将主存中一些经常访问的信息存放在高速缓存中,减少访问主存储器的次数,可大幅度提高程序执行速度。

通常,进程的程序和数据是存放在主存储器中,每当使用时,被临时复制到一个速度较快的高速缓存中。当 CPU 访问一组特定信息时,首先检查它是否在高速缓存中,如果已存在,可直接从中取出使用,以避免访问主存,否则,再从主存中读出信息。

 

磁盘缓存

 

由于目前磁盘的 I/O 速度远低于对主存的访问速度,因此将频繁使用的一部分磁盘数据和信息,暂时存放在磁盘缓存中,可减少访问磁盘的次数。磁盘缓存本身并不是一种实际存在的存储介质,它依托于固定磁盘,提供对主存储器存储空间的扩充,即利用主存中的存储空间,来暂存从磁盘中读出(或写入)的信息。主存也可以看做是辅存的高速缓存,因为,辅存中的数据必须复制到主存方能使用;反之,数据也必须先存在主存中,才能输出到辅存。

 

 

虚拟与存储体系

 


 

程序的装入和链接

 

在多道程序环境下,要使程序运行,必须先为之创建进程。而创建进程的第一件事,便是将程序和数据装入内存。如何将一个用户源程序变为一个可在内存中执行的程序,通常都要经过以下几个步骤:

  • 首先是要编译,由编译程序(Compiler)将用户源代码编译成若干个目标模块(Object Module);
  • 其次是链接,由链接程序(Linker)将编译后形成的一组目标模块,以及它们所需要的库函数链接在一起,形成一个完整的装入模块(Load Module);
  • 最后是装入,由装入程序(Loader)将装入模块装入内存。

 

程序的装入

 

绝对装入方式(Absolute Loading Mode)

在编译时,如果知道程序将驻留在内存的什么位置,那么,编译程序将产生绝对地址的目标代码。

绝对装入程序按照装入模块中的地址,将程序和数据装入内存。装入模块被装入内存后,由于程序中的逻辑地址与实际内存地址完全相同,故不须对程序和数据的地址进行修改。程序中所使用的绝对地址,既可在编译或汇编时给出,也可由程序员直接赋予。

 

可重定位装入方式(Relocation Loading Mode)

 

绝对装入方式只能将目标模块装入到内存中事先指定的位置。在多道程序环境下,编译程序不可能预知所编译的目标模块应放在内存的何处,因此,绝对装入方式只适用于单道程序环境。在多道程序环境下,所得到的目标模块的起始地址通常是从 0 开始的,程序中的其它地址也都是相对于起始地址计算的。此时应采用可重定位装入方式,根据内存的当前情况,将装入模块装入到内存的适当位置。

在采用可重定位装入程序将装入模块装入内存后,会使装入模块中的所有逻辑地址与实际装入内存的物理地址不同。因此数据地址和指令地址需要作出相应的修改。通常是把在装入时对目标程序中指令和数据的修改过程称为重定位。又因为地址变换通常是在装入时一次完成的,以后不再改变,故称为静态重定位。

 

动态运行时装入方式(Dynamic Run-time Loading)


可重定位装入方式可将装入模块装入到内存中任何允许的位置,故可用于多道程序环境;但这种方式并不允许程序运行时在内存中移动位置。因为,程序在内存中的移动,意味着它的物理位置发生了变化,这时必须对程序和数据的地址(是绝对地址)进行修改后方能运行。然而,实际情况是,在运行过程中它在内存中的位置可能经常要改变,此时就应采用动态运行时装入的方式。

动态运行时的装入程序在把装入模块装入内存后,并不立即把装入模块中的相对地址转换为绝对地址,而是把这种地址转换推迟到程序真正要执行时才进行。因此,装入内存后的所有地址都仍是相对地址。为使地址转换不影响指令的执行速度,这种方式需要一个重定位寄存器的支持。

 

 

程序的链接

 

源程序经过编译后,可得到一组目标模块,再利用链接程序将这组目标模块链接,形成装入模块。根据链接时间的不同,可把链接分成如下三种:

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

 


 

连续分配方式

 

连续分配方式,是指为一个用户程序分配一个连续的内存空间。

 

单一连续分配

 

这是最简单的一种存储管理方式,但只能用于单用户、单任务的操作系统中

采用这种存储管理方式时,可把内存分为系统区和用户区两部分,系统区仅提供给 OS 使用,通常是放在内存的低址部分;用户区是指除系统区以外的全部内存空间,提供给用户使用。

在单用户环境下,机器由一用户独占,不可能存在其他用户干扰的问题;这时可能出现的破坏行为也只是用户程序自己去破坏操作系统,其后果并不严重,只是会影响该用户程序的运行,且操作系统也很容易通过系统的再启动而重新装入内存。

 

 

固定分区分配

 

固定分区式分配是最简单的一种可运行多道程序的存储管理方式。这是将内存用户空间划分为若干个固定大小的区域,在每个分区中只装入一道作业,这样,把用户空间划分为几个分区,便允许有几道作业并发运行。当有一空闲分区时,便可以再从外存的后备作业队列中选择一个适当大小的作业装入该分区,当该作业结束时,又可再从后备作业队列中找出另一作业调入该分区。

 

 

 

 

划分分区的方法

 

可用下述两种方法将内存的用户空间划分为若干个固定大小的分区:

(1) 分区大小相等,即使所有的内存分区大小相等。其缺点是缺乏灵活性,即当程序太小时,会造成内存空间的浪费;当程序太大时,一个分区又不足以装入该程序,致使该程序无法运行。

(2) 分区大小不等。为了克服分区大小相等而缺乏灵活性的这个缺点,可把内存区划分成含有多个较小的分区、适量的中等分区及少量的大分区。这样,便可根据程序的大小为之分配适当的分区。

 

 

内存分配

 

为了便于内存分配,通常将分区按大小进行排队,并为之建立一张分区使用表,其中各表项包括每个分区的起始地址、大小及状态(是否已分配)。

当有一用户程序要装入时,由内存分配程序检索该表,从中找出一个能满足要求的、尚未分配的分区,将之分配给该程序,然后将该表项中的状态置为“已分配”;若未找到大小足够的分区,则拒绝为该用户程序分配内存。

 

动态分区分配

 

动态分区分配是根据进程的实际需要,动态地为之分配内存空间。在实现可变分区分配时,将涉及到分区分配中所用的数据结构、分区分配算法和分区的分配与回收操作这样三个问题。

 

分区分配中的数据结构

 

为了实现分区分配,系统中必须配置相应的数据结构,用来描述空闲分区和已分配分区的情况,为分配提供依据。常用的数据结构有以下两种形式:

  • (1) 空闲分区表。在系统中设置一张空闲分区表,用于记录每个空闲分区的情况。每个空闲分区占一个表目,表目中包括分区序号、分区始址及分区的大小等数据项。
  • (2) 空闲分区链。为了实现对空闲分区的分配和链接,在每个分区的起始部分,设置一些用于控制分区分配的信息,以及用于链接各分区所用的前向指针;在分区尾部则设置一后向指针,通过前、后向链接指针,可将所有的空闲分区链接成一个双向链

 

 

分区分配算法

 

为把一个新作业装入内存,须按照一定的分配算法,从空闲分区表或空闲分区链中选出一分区分配给该作业。目前常用以下所述的五种分配算法。

 

首次适应算法(first fit)


在分配内存时,从链首开始顺序查找,直至找到一个大小能满足要求的空闲分区为止;然后再按照作业的大小,从该分区中划出一块内存空间分配给请求者,余下的空闲分区仍留在空闲链中。

若从链首直至链尾都不能找到一个能满足要求的分区,则此次内存分配失败,返回。该算法倾向于优先利用内存中低址部分的空闲分区,从而保留了高址部分的大空闲区。这给为以后到达的大作业分配大的内存空间创造了条件。其缺点是低址部分不断被划分,会留下许多难以利用的、很小的空闲分区,而每次查找又都是从低址部分开始,这无疑会增加查找可用空闲分区时的开销。

 

循环首次适应算法(next fit)

在为进程分配内存空间时,不再是每次都从链首开始查找,而是从上次找到的空闲分区的下一个空闲分区开始查找,直至找到一个能满足要求的空闲分区,从中划出一块与请求大小相等的内存空间分配给作业。

该算法能使内存中的空闲分区分布得更均匀,从而减少了查找空闲分区时的开销,但这样会缺乏大的空闲分区

 

最佳适应算法(best fit)

所谓“最佳”是指每次为作业分配内存时,总是把能满足要求、又是最小的空闲分区分配给作业,避免“大材小用”。

为了加速寻找,该算法要求将所有的空闲分区按其容量以从小到大的顺序形成一空闲分区链。这样,第一次找到的能满足要求的空闲区,必然是最佳的。孤立地看,最佳适应算法似乎是最佳的,然而在宏观上却不一定。因为每次分配后所切割下来的剩余部分总是最小的,这样,在存储器中会留下许多难以利用的小空闲区

 

最坏适应算法(worst fit)

最坏适应分配算法要扫描整个空闲分区表或链表,总是挑选一个最大的空闲区分割给作业使用,其优点是可使剩下的空闲区不至于太小,产生碎片的几率最小,对中、小作业有利,同时最坏适应分配算法查找效率很高。该算法要求将所有的空闲分区按其容量以从大到小的顺序形成一空闲分区链,查找时只要看第一个分区能否满足作业要求。但是该算法的缺点也是明显的,它会使存储器中缺乏大的空闲分区。

最坏适应算法、首次适应算法、循环首次适应算法、最佳适应算法一起,也称为顺序搜索法。

 

快速适应算法(quick fit)

该算法又称为分类搜索法,是将空闲分区根据其容量大小进行分类,对于每一类具有相同容量的所有空闲分区,单独设立一个空闲分区链表,这样,系统中存在多个空闲分区链表,同时在内存中设立一张管理索引表,该表的每一个表项对应了一种空闲分区类型,并记录了该类型空闲分区链表表头的指针。

空闲分区的分类是根据进程常用的空间大小进行划分。

该算法的优点是查找效率高,仅需要根据进程的长度,寻找到能容纳它的最小空闲区链表,并取下第一块进行分配即可。另外该算法在进行空闲分区分配时,不会对任何分区产生分割,所以能保留大的分区,满足对大空间的需求,也不会产生内存碎片。该算法的缺点是在分区归还主存时算法复杂,系统开销较大。此外,该算法在分配空闲分区时是以进程为单位,一个分区只属于一个进程,因此在为进程所分配的一个分区中,或多或少地存在一定的浪费。空闲分区划分越细,浪费则越严重,整体上会造成可观的存储空间浪费,这是典型的以空间换时间的作法

 

 

分区分配操作

 

在动态分区存储管理方式中,主要的操作是分配内存和回收内存。

 

分配内存

系统应利用某种分配算法,从空闲分区链(表)中找到所需大小的分区。设请求的分区大小为 u.size,表中每个空闲分区的大小可表示为 m.size。若 m.size-u.size≤size(size 是事先规定的不再切割的剩余分区的大小),说明多余部分太小,可不再切割,将整个分区分配给请求者;否则(即多余部分超过 size),从该分区中按请求的大小划分出一块内存空间分配出去,余下的部分仍留在空闲分区链(表)中。然后,将分配区的首址返回给调用者。

 

 回收内存

当进程运行完毕释放内存时,系统根据回收区的首址,从空闲区链(表)中找到相应的插入点。

 

 

 

伙伴系统

 

伙伴系统是linux底层内存管理所使用的方案,一种特殊的分离适配算法。

 

主要思想

  • 将内存按2的幂次进行划分,组成若干空闲块链表;
  • 查找该链表找到能满足进程需求的最佳匹配块

 

算法

 

伙伴系统的例子

上图中内存过程:

首先将1M分成两份,每份512k。之后将512k分成两份,每份256k,再将256划分出两个128.将左侧的128分配给A

对于进程B,直接将第一个256k的块分配给他。

。。。。。。

释放C时,由于c原来的64k旁边的64k也是空闲的,因此将两块合并成一块128k的空闲块。

 

 

 

可重定位分区分配

 

动态重定位的引入

 

在连续分配方式中,必须把一个系统或用户程序装入一连续的内存空间。如果在系统中只有若干个小的分区,即使它们容量的总和大于要装入的程序,但由于这些分区不相邻接,也无法把该程序装入内存。这种不能被利用的小分区称为“零头”或“碎片”。

若想把作业装入,可采用的一种方法是:将内存中的所有作业进行移动,使它们全都相邻接,这样,即可把原来分散的多个小分区拼接成一个大分区,这时就可把作业装入该区。这种通过移动内存中作业的位置,以把原来多个分散的小分区拼接成一个大分区的方法,称为“拼接”或“紧凑”。

由于经过紧凑后的某些用户程序在内存中的位置发生了变化,此时若不对程序和数据的地址加以修改(变换),则程序必将无法执行。为此,在每次“紧凑”后,都必须对移动了的程序或数据进行重定位。

 

动态重定位的实现

 

在动态运行时装入的方式中,作业装入内存后的所有地址都仍然是相对地址,将相对地址转换为物理地址的工作,被推迟到程序指令要真正执行时进行。为使地址的转换不会影响到指令的执行速度,必须有硬件地址变换机构的支持,即须在系统中增设一个重定位寄存器,用它来存放程序(数据)在内存中的起始地址

程序在执行时,真正访问的内存地址是相对地址与重定位寄存器中的地址相加而形成的。地址变换过程是在程序执行期间,随着对每条指令或数据的访问自动进行的,故称为动态重定位。当系统对内存进行了“紧凑”而使若干程序从内存的某处移至另一处时,不需对程序做任何修改,只要用该程序在内存的新起始地址,去置换原来的起始地址即可。

 

动态重定位分区分配算法

 

动态重定位分区分配算法与动态分区分配算法基本上相同,差别仅在于:在这种分配算法中,增加了紧凑的功能,通常,在找不到足够大的空闲分区来满足用户需求时进行紧凑。

 

对换

 

对换(Swapping)的引入


在多道程序环境下,一方面,在内存中的某些进程由于某事件尚未发生而被阻塞运行,但它却占用了大量的内存空间,甚至有时可能出现在内存中所有进程都被阻塞而迫使 CPU停止下来等待的情况;另一方面,却又有着许多作业在外存上等待,因无内存而不能进入内存运行的情况。显然这对系统资源是一种严重的浪费,且使系统吞吐量下降。为了解决这一问题,在系统中又增设了对换(也称交换)设施。

所谓“对换”,是指把内存中暂时不能运行的进程或者暂时不用的程序和数据调出到外存上,以便腾出足够的内存空间,再把已具备运行条件的进程或进程所需要的程序和数据调入内存。对换是提高内存利用率的有效措施。

 


对换空间的管理


在具有对换功能的 OS 中,通常把外存分为文件区和对换区。前者用于存放文件,后者用于存放从内存换出的进程。由于通常的文件都是较长久地驻留在外存上,故对文件区管理的主要目标,是提高文件存储空间的利用率,为此,对文件区采取离散分配方式。然而,进程在对换区中驻留的时间是短暂的,对换操作又较频繁,故对对换空间管理的主要目标,是提高进程换入和换出的速度。为此,采取的是连续分配方式,较少考虑外存中的碎片问题。为了能对对换区中的空闲盘块进行管理,在系统中应配置相应的数据结构,以记录外存的使用情况。其形式与内存在动态分区分配方式中所用数据结构相似,即同样可以用空闲分区表或空闲分区链。在空闲分区表中的每个表目中应包含两项,即对换区的首址及其大小,分别用盘块号和盘块数表示。由于对换分区的分配是采用连续分配方式,因而对换空间的分配与回收,与动态分区方式时的内存分配与回收方法雷同。其分配算法可以是首次适应算法、循环首次适应算法或最佳适应算法。

 


进程的换出与换入


(1) 进程的换出。每当一进程由于创建子进程而需要更多的内存空间,但又无足够的内存空间等情况发生时,系统应将某进程换出。其过程是:系统首先选择处于阻塞状态且优先级最低的进程作为换出进程,然后启动磁盘,将该进程的程序和数据传送到磁盘的对换区上。若传送过程未出现错误,便可回收该进程所占用的内存空间,并对该进程的进程控制块做相应的修改。

(2) 进程的换入。系统应定时地查看所有进程的状态,从中找出“就绪”状态但已换出的进程,将其中换出时间最久(换出到磁盘上)的进程作为换入进程,将之换入,直至已无可换入的进程或无可换出的进程为止。

 


 

基本分页存储管理方式

 

连续分配方式会形成许多“碎片”,虽然可通过“紧凑”方法将许多碎片拼接成可用的大块空间,但须为之付出很大开销。如果允许将一个进程直接分散地装入到许多不相邻接的分区中,则无须再进行“紧凑”。基于这一思想而产生了离散分配方式。

  • 如果离散分配的基本单位是页,则称为分页存储管理方式;
  • 如果离散分配的基本单位是段,则称为分段存储管理方式。

在分页存储管理方式中,如果不具备页面对换功能,则称为基本的分页存储管理方式,或称为纯分页存储管理方式,它不具有支持实现虚拟存储器的功能,它要求把每个作业全部装入内存后方能运行。

 

页面与页表

 

页面

 

页面和物理块

分页存储管理是

  • 将一个进程的逻辑地址空间分成若干个大小相等的片,称为页面或页,并为各页加以编号,从 0 开始。
  • 把内存空间分成与页面相同大小的若干个存储块,称为(物理)块或页框(frame),也同样为它们加以编号。

在为进程分配内存时,以块为单位将进程中的若干个页分别装入到多个可以不相邻接的物理块中

上图中,虚地址空间中的0号页面被加载到内存的0k-4k的页框内,1号页面被加载到内存4k-8k的页框内。

 

页面大小

在分页系统中的页面其大小应适中。页面大小应是 2 的幂,通常为 512 B~8 KB。

 

地址结构
分页地址中的地址结构如下:

它含有两部分:前一部分为页号 P,后一部分为位移量 W(或称为页内地址)。图中的地址长度为 32 位,其中 0~11 位为页内地址,即每页的大小为 4 KB;12~31 位为页号,地址空间最多允许有 1 M 页。

 

页表

在分页系统中,允许将进程的各个页离散地存储在内存不同的物理块中,但系统应能保证进程的正确运行,即能在内存中找到每个页面所对应的物理块。为此,系统又为每个进程建立了一张页面映像表,简称页表。在进程地址空间内的所有页(0~n),依次在页表中有一页表项,其中记录了相应页在内存中对应的物理块号。在配置了页表后,进程执行时,通过查找该表,即可找到每页在内存中的物理块号。可见,页表的作用是实现从页号到物理块号的地址映射

即使在简单的分页系统中,也常在页表的表项中设置一存取控制字段,用于对该存储块中的内容加以保护。

  • 当存取控制字段仅有一位时,可用来规定该存储块中的内容是允许读/写,还是只读;
  • 若存取控制字段为二位,则可规定为读/写、只读和只执行等存取方式。

如果有一进程试图去写一个只允许读的存储块时,将引起操作系统的一次中断

 

 

地址变换机构

 

为了能将用户地址空间中的逻辑地址变换为内存空间中的物理地址,在系统中必须设置地址变换机构。该机构的基本任务是实现从逻辑地址到物理地址的转换。由于页内地址和物理地址是一一对应的(例如,对于页面大小是 1 KB 的页内地址是 0~1023,其相应的物理块内的地址也是 0~1023,无须再进行转换),因此,地址变换机构的任务实际上只是将逻辑地址中的页号,转换为内存中的物理块号。又因为页面映射表的作用就是用于实现从页号到物理块号的变换,因此,地址变换任务是借助于页表来完成的

 

基本的地址变换机构


页表的功能可以由一组专门的寄存器来实现。一个页表项用一个寄存器。由于寄存器具有较高的访问速度,因而有利于提高地址变换的速度;由于寄存器成本较高,且大多数现代计算机的页表又可能很大,使页表项的总数可达几千甚至几十万个,显然这些页表项不可能都用寄存器来实现,因此,页表大多驻留在内存中

在系统中只设置一个页表寄存器 PTR(Page-Table Register),在其中存放页表在内存的始址和页表的长度。平时,进程未执行时,页表的始址和页表长度存放在本进程的 PCB 中。当调度程序调度到某进程时,才将这两个数据装入页表寄存器中。因此,在单处理机环境下,虽然系统中可以运行多个进程,但只需一个页表寄存器。当进程要访问某个逻辑地址中的数据时,分页地址变换机构会自动地将有效地址(相对地址)分为页号和页内地址两部分,再以页号为索引去检索页表。查找操作由硬件执行。

在执行检索之前,先将页号与页表长度进行比较,如果页号大于或等于页表长度,则表示本次所访问的地址已超越进程的地址空间。于是,这一错误将被系统发现并产生一地址越界中断。若未出现越界错误,则将页表始址与页号和页表项长度的乘积相加,便得到该表项在页表中的位置,于是可从中得到该页的物理块号,将之装入物理地址寄存器中。与此同时,再将有效地址寄存器中的页内地址送入物理地址寄存器的块内地址字段中。这样便完成了从逻辑地址到物理地址的变换

具有快表的地址变换机构

由于页表是存放在内存中的,这使 CPU 在每存取一个数据时,都要两次访问内存。

  • 第一次是访问内存中的页表,从中找到指定页的物理块号,再将块号与页内偏移量 W 拼接,以形成物理地址。
  • 第二次访问内存时,才是从第一次所得地址中获得所需数据(或向此地址中写入数据)。

因此,采用这种方式将使计算机的处理速度降低近 1/2。可见,以此高昂代价来换取存储器空间利用率的提高,是得不偿失的。为了提高地址变换速度,可在地址变换机构中增设一个具有并行查寻能力的特殊高速缓冲寄存器,又称为“联想寄器”(Associative Memory),或称为“快表”,

此时的地址变换过程是:在 CPU 给出有效地址后,由地址变换机构自动地将页号 P 送入高速缓冲寄存器,并将此页号与高速缓存中的所有页号进行比较,

  • 若其中有与此相匹配的页号,便表示所要访问的页表项在快表中。于是,可直接从快表中读出该页所对应的物理块号,并送到物理地址寄存器中。
  • 如在块表中未找到对应的页表项,则还须再访问内存中的页表,找到后,把从页表项中读出的物理块号送地址寄存器;同时,再将此页表项存入快表的一个寄存器单元中,亦即,重新修改快表。
  • 但如果联想寄存器已满,则 OS 必须找到一个老的且已被认为不再需要的页表项,将它换出。

 

 

两级和多级页表

 

现代的大多数计算机系统,都支持非常大的逻辑地址空间(2 32 ~2 64 )。在这样的环境下,页表就变得非常大,而且还要求是连续的。显然这是不现实的,我们可以采用下述两个方法来解决这一问题:

  • (1) 采用离散分配方式来解决难以找到一块连续的大内存空间的问题;
  • (2) 只将当前需要的部分页表项调入内存,其余的页表项仍驻留在磁盘上,需要时再调入。

 

两级页表(Two-Level Page Table)


对于要求连续的内存空间来存放页表的问题,可利用将页表进行分页,并离散地将各个页面分别存放在不同的物理块中的办法来加以解决,同样也要为离散分配的页表再建立一张页表,称为外层页表(Outer Page Table),在每个页表项中记录了页表页面的物理块号。

为了地址变换实现上的方便起见,在地址变换机构中同样需要增设一个外层页表寄存器,用于存放外层页表的始址,并利用逻辑地址中的外层页号,作为外层页表的索引,从中找到指定页表分页的始址,再利用 P 2 作为指定页表分页的索引,找到指定的页表项,其中即含有该页在内存的物理块号,用该块号和页内地址 d 即可构成访问的内存物理地址。

上述对页表施行离散分配的方法,虽然解决了对大页表无需大片存储空间的问题,但并未解决用较少的内存空间去存放大页表的问题。换言之,只用离散分配空间的办法并未减少页表所占用的内存空间。解决方法是把当前需要的一批页表项调入内存,以后再根据需要陆续调入。在采用两级页表结构的情况下,对于正在运行的进程,必须将其外层页表调入内存,而对页表则只需调入一页或几页。

 

 


 

基本分段存储管理方式

 

分段系统的基本原理

 

分段

在分段存储管理方式中,作业的地址空间被划分为若干个段,每个段定义了一组逻辑信息。分段地址中的地址具有如下结构:

 

段表

分段式存储管理系统中,为每个分段分配一个连续的分区,而进程中的各个段可以离散地移入内存中不同的分区中。为使程序能正常运行,亦即,能从物理内存中找出每个逻辑段所对应的位置,应像分页系统那样,在系统中为每个进程建立一张段映射表,简称“段表”。

每个段在表中占有一个表项,其中记录了该段在内存中的起始地址(又称为“基址”)和段的长度。段表可以存放在一组寄存器中,这样有利于提高地址转换速度,但更常见的是将段表放在内存中。段表用于实现从逻辑段到物理内存区的映射。

 


 

页面置换算法

 

在进程运行过程中,若其所要访问的页面不在内存而需把它们调入内存,但内存已无空闲空间时,为了保证该进程能正常运行,系统必须从内存中调出一页程序或数据送磁盘的对换区中。

 

最佳(Optimal)置换算法

采用最佳置换算法,通常可保证获得最低的缺页率。但由于人们目前还无法预知一个进程在内存的若干个页面中,哪一个页面是未来最长时间内不再被访问的,因而该算法是无法实现的,但可以利用该算法去评价其它算法。

 

先进先出(FIFO)页面置换算法

该算法把一个进程已调入内存的页面,按先后次序链接成一个队列,并设置一个指针,称为替换指针,使它总是指向最老的页面。

 

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

最近最久未使用(LRU)的页面置换算法,是根据页面调入内存后的使用情况进行决策的。由于无法预测各页面将来的使用情况,只能利用“最近的过去”作为“最近的将来”的近似,因此,LRU 置换算法是选择最近最久未使用的页面予以淘汰

 

 


0330补充

 

地址重定位

 

  • 逻辑地址——进程中的地址是逻辑地址,并不是最终的物理地址,不能通过逻辑地址在内存中读取信息

  • 物理地址——内存中存储单元的地址,可以直接寻址

 

 

 

页式存储管理方案

 

设计思想

  • 用户进程地址空间被划分成大小相等的部分,称为页面,从0开始编号(划分由系统完成,对用户透明
  • 内存空间按同样大小划分为大小相等的区域,称为页框,从0号开始编号

 

内存分配规则

以页为单位进行分配,并按进程需要的页数来分配;逻辑上相邻的页,物理上不一定相邻

典型页面尺寸——4k或4M

 

逻辑地址

 

通过页表记录逻辑地址和物理地址之间的对应关系

 

 

段式存储管理方案

 

设计思想

  • 用户进程地址空间按程序自身的逻辑关系划分为若干个程序段,每个程序段都有一个段名。
  • 内存空间动态划分为若干长度不同的区域,称为物理段,每个物理段由起始地址和长度确定。

 

内存分配规则

以段位单位进行分配,每段在内存中占据连续空间,但各段之间可以不相邻。

 

段式存储管理方案的示意

程序分成了五段。运行到对应的地址时,调用相应的段

通过段表,可以构建起段和物理地址之间的映射关系

 

 

 

段页式存储管理方案

 

设计思想

用户程序先划分成段,再将段划分成各个等长的页。

 

数据机构和相关操作

 

 

 

交换技术

 

如何实现将大的进程地址空间存入小的物理内存中?

解决方案——内存扩充技术——有以下四种

 

覆盖技术

 

程序大小超过物理内存总和时,在程序执行过程中,程序的不同部分在内存中相互替代

  • 按照程序自身的逻辑结构,将那些不会同时执行的程序段共享同一块内存区域
  • 要求程序各个模块之间有明确的调用结构
  • 程序员声明覆盖结构,操作系统完成自动覆盖。

 

覆盖技术示例

 

 

交换技术

 

内存空间紧张时,系统将内存中某些进程暂时移动到外存,把外存中某些进程交换进内存,占据前者所占用的区域。

交换的内容——栈和堆中的内容。代码和静态的数据不需要交换,因为在可执行文件中这些内容都有。

交换区——一般系统会指定一块特殊的磁盘区域作为交换空间,包含连续的磁道,操作系统可以使用底层的磁盘低些操作对其高效访问

何时交换

  • 很少再用
  • 内存空间不够或者有不够的危险时

哪些进程不能随意发生交换——哪些处于等待IO状态的进程

 


 

 

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值