• 计算机操作系统之存储器管理


    程序运行

    将用户的一个源程序变成一个可在内存中执行的程序,通常要经过以下几个步骤:

    1、编译:由编译程序,将程序编译成若干个目标模块

    2、链接:由链接程序将编译后形成的一组目标模块,以及他们所需要的库函数链接在一起,形成一个完整的装入模块。

    3、装入:由装入程序将装入模块装入内存

    具体讨论一下如何把一个装入模块,装入内存:

    1、绝对装入方式:编译程序产生带有绝对地址的目标代码,只适合于单道程序环境。

    2、可重定位装入方式:所得到的模块都是以0开始的,程序中的其它地址也都是相对于起始地址计算的,此时可重定位装入方式,根据内存的情况,将装入模块装入到内存的适当位置。通常把在装入时对目标程序中指令和数据的修改过程称为重定位。又因为地址变换通常是在装入时一次完成的,以后不再改变,故称为静态重定位

    3、动态运行时装入方式:上一种方式,可将装入模块装入到内存中任何位置,故可用于多道程序环境,但并不允许程序运行时在内存中移动位置。而动态运行时装入方式,是在把装入内存后,并不立即把装入模块中的相对地址转换为绝对地址,而是把这种地址转换推迟到程序真正要执行时才进行。因此,装入内存后的所有地址都仍是相对地址。为了不影响转换带来的不良影响,一般使用一个重定位寄存器

    程序的链接

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

    1、静态链接:在程序运行之前,先将各目标模块和它们的所用的链接库,链接成一个完整的装配模块,以后不再拆开。

    2、装入时动态链接:在把一系列的目标模块装入内存时,采用边装入边链接的链接方式。

    3、运行时动态链接:这是指对某些目标模块的链接,是在程序执行中要该模块时,才对它进行链接。

    对换:为什么要用到对换?

    在多道程序环境下,在内存中的某些进程由于某事件尚未发生,而被阻塞了,但它却占用了大量的内存空间,另一方面,其他的作业却在外存上等待。这样就形成了浪费。因此引用了“对换”这个概念。

    对换是把内存中能运行的进程或者暂时不用的程序和数据,调出到外存上,以便腾出足够的内存,再把已经具备运行条件的进程或进程所需要的程序和数据,调入内存。

    如果对换的单位是整个进程,则称为整体对换,如果对换的单位是段或页,则称为部分对换。

    对换空间的管理

    在具有对换功能的OS中,通常把外存分为文件区和对换区。前者用于存放文件,后者用于存放从内存换出的进程。

    由于对换分区的分配是连续分配方式,因而对换空间的分配与回收,与动态分区方式时的内存分配与回收方法雷同。一般用首次适应算法,循环首次适应算法或最佳适应算法。

    进程的换入与换出:

    1、如果某一个进程被阻塞了或是优先级最低的,一般会把它的程序与数据换出到对换区

    2、系统应定时地查看所有的进程的状态,从中找出“就绪”状态但已经换出的进程,将其中换出时间最久的进程作为换入进程,将之换入。

    基本的分页存储管理方式

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

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

    页面与物理块

    分页存储管理,是将一个进程的逻辑地址空间分成若干个大小相等的片,称为页面。也把内存空间分成和页面大小相等的存储块,称为物理块或页框。由于进程的最后一页经常装不满一块而形成了不可利用的碎片,称为“页内碎片”

    页面的大小

    页面太小,可以减小页内碎片,提高利用率。但是这样会使得页表过长。如果页面过大,虽然页面可以变得很短,但是页内碎片太大。所以一般选择大小适中,且页面大小就是2的幂,通常是512B-8KB

    地址结构

    分页地址中的地址如下:

    一共32位,0-11位是位移量(页内地址,所以一页为4KB), 12-31是页号,所以最多可以有1M页。

    地址变换机构---页表

    为了能将用户地址空间中逻辑地址,变换为内存空间中的物理地址,在系统中必须设置地址变换机构。该机构的基本任务是实现从逻辑地址到物理地址的转换。由于页面内的地址与物理块内的地址是一一对应的。所以只要把逻辑地址的页号转换为内存中的物理块号就可以了。

    而页面映射表(页表)就是用于实现从页号到物理块号的变换。因此,地址变换的任务是借助于页表来完成的。

    clip_image001

    基本的地址变换机构

    页表的功能可以借助一组专门的寄存器来实现。一个页表项用一个寄存器来实现,但是由于页表太长,寄存器比较小,而且贵。所以一般把页表放在内存上。在系统中只设置一个页表寄存器PTR,在其中存入页表在内存中的始址和大小。当程序未执行时,这两个值是放在PCB中的。当调度程序调度到某个进程时,才将这两个数据装入页表寄存器中。因此在单处理机环境下,虽然系统中可以运行多个进程,但只要一个PTR就可以。

    当进程要访问某个逻辑地址中的数据时,分页地址变换机构会自动地将有效地址分为页号和页内地址两部分。再以页号为索引去检索页表。查找操作由硬件来执行,提高效率。首先判断是不是越界,如果不越界,则将页表始址与页号和页表项长度的乘积相加,便得到该表项在页表中的位置,于是可从中得到该页的物理块号,将之装入物理地址寄存器中。与此同时,再将有效地址寄存器中的页内地址送入物理地址寄存器的块内地址字段中。这样便完成了从逻辑地址到物理地址的变换。

    clip_image002

    具有快表的地址变换机构

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

    第一次,是找到指定页面的物理块号,再将物理块号和页内地址相加,得到物理地址。

    第二次,从第一次得到的地址中,把对应的数据找到。

    那现在有没有改进的方案呢。是不是可以不用第一次访存呢?如果不需要的话,那应该有一个地方存储这个页表,或页表的一部分。

    为了提高地址变换速度,可在地址变换机构中,增设一个具有并行查寻能力的特殊高速缓冲寄存器,又称为“联想寄存器”或快表。

    此时的地址变换过程是这样子的:

    在CPU给出有效地址后,由地址变换机构自动地将页号P送入高速缓冲寄存器,并将此页号与高速缓存中的所有页号进行比较,若其中有与此相匹配的页号,便送到物理地址寄存器中。如在快表中未找到对应的页表项,则还须再访问内存中的页表。找到后,把从页表项中读出的物理块号送到地址寄存器,同时,再将此页表项存入快表的一个突破器单元中,即重修快表。但如果此快表已经满了,则OS必须找到一个老的且已经被认为不再需要的页表项,将它换出。

    由于成本的考虑,快表不可能做的太大,一般只存16-512个页表项。

    clip_image004

    现在的计算机还可以有两级和多级页表

    基本的分段存储管理方式

    如果说推动存储管理方式从固定分区到动态分区分配,进而又发展到分页存储管理方式的主要动力,是提高内存利用率,那么引入分段存储管理方式的目的,则主要是为了满足用户(程序员)在编程和使用上多方面的要求。

    1) 方便编程

    通常,用户把自己的作业按照逻辑关系划分为若干个段,每个段都是从0开始的。并且有自己的名字和长度。因此,希望要访问的逻辑地址是由段名和段内地址偏移量决定的。如下指令:

    Load 1 ,[A]|<d> 其中,含义是将分段A中D单元内的值读入到寄存器1.

    2) 信息共享

    在实现程序和数据的共享时,是以信息的逻辑单位为基础的。比如共享某个函数,页面只是存放信息的物理块,不具备完整的意义。而段是信息的逻辑单位。为了实现段的共享,希望存储管理能与用户程序分段的组织方式相适应。

    3) 信息保护

    同样是对信息的逻辑单位进行保护

    4) 动态增长

    在实际应用中,有些段,特别是数据段,是不断增长的,而事先无法知道大小。分段存储管理可以很好的解决这个问题。

    5) 动态链接

    在作业运行之前,并不是把几个目标程序段链接起来。要运行时,先将主程序对应的目标程序装入内存启动运行,当运行过程中又要调用某段时,才将该段调入内存并进行链接。可见,动态链接也要求以段作为管理的单位。

    分段系统的基本原理

    1 分段原理

    在分段存储管理方式中,作业的地址空间被划分为若干个段,每个段定义了一组逻辑信息。例如主程序段,子程序段,数据段,栈段。为了实现简单起见,通常可用一个段号来代替段名,每个段都从0开始编址,并采用一段连续的地址空间。

    对于一个作业,由于是分成多个段,因而是一个二维的。所以说逻辑地址是由段号和段内地址组成的。

    2 段表

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

    每个段在表中占有一个表项,其中记录了该段在内存中的起始地址和段的长度。段表可以放在寄存器中,这样有利于提高地址转换速度;但更常见的是把段表放在内存中。在配置了段表后,执行中的进程可通过查找段表,找到每个段所对应的内存区。可见,段表是用于实现从逻辑到物理内存区的映射。

    clip_image005

    3 地址变换机构

    为了实现从进程的逻辑地址到物理地址的变换功能,在系统中设置了段表寄存器,用于存放段表始址和段表长度。在进行地址变换时,系统将逻辑地址中的段号与段表长度进行比较,如果段号太大,表示越界,于是产生越界中断信息。如果没有越界,则用段表的始址+段号,得到所在段表的项。之后,就找到了此段的基址。然后,决断位移量与此段的长度大小,如果越界,发现越界中断信息,否则就可以找到物理地址了。

    clip_image007

    4 分页与分段的区别

    1) 页是信息的物理单位,分页是为了实现离散分配方式,以消减内存的外零头提高内存的利用率。分页只是为了系统管理的需要;而分段则是为了程序员的需要。

    2) 页的大小固定且由系统决定,由系统把逻辑地址划分为页号和页内地址两部分,是由机器硬件实现的。所以说系统中只有一种长度的页面。而段的长度不是固定的,决定它的长度的是用户编写的程序。通常是编译程序在对源程序进行编译时,根据信息的性质来划分。

    3) 分页的作业地址空间是一维的,即单一的线性地址空间,而分段的作业地址是二维的。

    段页式存储管理

    我们知道了分页可以提高内存的利用率,而分段则可以实现信息保护,信息共享,动态链接,动态增长等,那能不能合二为一呢?这就是段页式存储管理。

    基本原理

    先把用户程序分成若干段,再把每一个段分成若干个页面。如一个作业有三个段,页面大小为4KB。在段页式系统中,其地址结构由段号,段内页号及页内地址三部分所组成。如下图:

    clip_image009

    地址变换过程

    为了方便实现地址变换,须配置一个段表寄存器,其中存放段表始址和段长。过程如下:

    clip_image011

    在段页式系统中,为了得到一个数据,要进行三次访问内存。

    1、第一次访问内存的段表,从中取得页表的始址;

    2、第二次访问是访问内存的页表,取得物理块号;

    3、第三次访问才是真正从第二次访问所得的地址中,取出指令和数据;

    虚拟存储器的基本概念

    在前面所讲的两种存储管理方式中,都要求将一个作业全部装入内存后方能运行,于是出现了两种情况:

    1、有的作业很大,不可能一下子装入内存

    2、有大量作业要求运行时,但由于内存容量不足以容纳所有的这些作业,只能将少数作业装入内存让它们先运行,而将其它大量的作业放在外存上等待。

    解决上述问题:

    1、最常见的是扩大内存。但这往往受到机器自身的限制,而且无疑要增加系统成本;

    2、另一种方法是从逻辑上扩充内存容量,这下是虚拟存储技术。

    虚拟存储器的引入

    常规存储管理方式的特征

    1、一次性:一次装入。

    2、驻留性:作业从装入内存,便一直驻留在内存中,直到作业运行结束。尽管在整个进程中,可能有多次IO,但是它仍然占用着内存。

    局部性原理

    1、时间局限性:如果程序中的某条指令一旦执行,则不久以后该指令可能再次执行,如果一个数据被访问过,则不久以后,还可能再次被访问。

    2、空间局限性:一旦程序访问了某个存储单元,在不久以后,其附近的存储单元也将被访问,即程序在一段时间内所访问的地址,可能集中在一定的范围之内。典型的例子是顺序执行。

    虚拟存储器的定义

    是指具有请求调入功能和置换功能,能从逻辑上对内存容量加以扩充的一种存储器系统。其逻辑容量由内存容量和外在容量之后所决定,其运行速度接近于内存速度,每位的成本接近于外存。所以是一个很好的解决方案。

    虚拟存储器的实现方法

    它的实现,都是建立在离散分配的存储管理方式的基础上。一般有两种方法:

    1、分页请求系统

    2、请求分段系统

  • 相关阅读:
    品味性能之道<六>:图形化SQL分析工具
    品味性能之道<五>:SQL分析工具
    品味性能之道<四>:管理重于技术
    品味性能之道<三>:方法论
    品味性能之道<二>:性能工程师可以具备的专业素养
    品味性能之道<一>:性能测试思维与误区
    网络协议学习笔记
    Java内存泄露监控工具:JVM监控工具介绍
    Loadrunner脚本回放无法准确定位欲删除元素
    C++ 虚函数
  • 原文地址:https://www.cnblogs.com/dgy5554/p/3984707.html
Copyright © 2020-2023  润新知