Jason Zhou的Coding之路 凡是过往皆为序章

操作系统学习笔记四 存储器管理


本节主要讨论计算机系统的存储器中内存管理的部分。包括程序的装入链接,连续分配,基本分页/分段存储管理方式,虚拟存储器的概念,请求分页存储管理方式,页面置换算法,请求分段存储管理方式等。

存储器的层次结构

  • CPU 寄存器(寄存器)->主存(高速缓存->主存->磁盘缓存)->(磁盘->可移动存储介质)。

程序的装入和连接

程序装入的步骤:编译, 链接, 装入程序。

程序的装入

  • 绝对装入方式:程序中使用绝对地址,即在编译或汇编时给出,也可以由程序员直接赋予(这需要了解内存使用情况)。多道程序环境难以实现。
  • 可重定位装入方式:装入后需要对指令地址和数据地址均进行重定位(装入时,对目标程序中指令和数据地址的修改过程)。这种方法通常仅在装入时需要进行地址变换,所以称为静态重定位
  • 动态运行时装入方式:装入程序时不把相对地址换成绝对地址,而是在程序真正执行时才转换地址。

程序的链接

程序的链接:将程序的各个目标模块和库等链接形成装入模块。

  • 静态链接方式:需要解决两个问题:对相对地址进行修改(排列),变换外部调用符号。
  • 装入时动态链接:边装入边链接。装入的模块,发生外部调用,则入查找相应外部模块,将器装入内存,并进行链接。便于修改和更新,便于实现对目标模块的共享。
  • 运行时动态链接:对某些模块推迟到程序执行时才装入内存并链接。

连续分配方式

单一连续分配

  • 分为系统区和用户区两部分。只能用于单用户、单任务操作系统。

固定分区分配

  • 分区大小固定,不随程序变化。
  • 划分分区方法:分区大小相等和分区大小不等两种
  • 内存分配:建立分区使用表,按照分区大小排列,使用时检索有无满足大小的未使用分区,有则分配。

动态分区分配

  • 根据进程实际需要动态为之分配内存空间。

动态分配的数据结构

  • 空闲分区表:记录每个空闲分区情况。包括空闲分区号,分区始地址和分区大小。
  • 空闲分区链:双链表,每个结点的前部和后部分别保持向前和向后的指针,空闲链结点的大小(重复),状态位(重复)。

分区分配算法

  • 首次适应算法 FF, first fit:留下更大的空闲分区。
  • 循环首次适应算法 next fit:上次找到空闲分区的下一个分区开始查找。空闲分区更均匀。
  • 最佳适应算法 best fit:分配满足要求的最小空闲分区。要求空闲分区以大小排序。
  • 最坏适应算法 worst fit:挑选最大空闲分区给作业使用。
  • 快速适应算法 quick fit:根据分区大小划分不同的空闲分区链,建索引表用于查找所需空闲分区链表,不在分割空闲分区。以空间换时间的做法,划分越细资源浪费越严重。

分区分配操作

  • 分区分配流程
  • 回收内存:有邻接则合并不分配新表项,无邻接则分配新表项插入空闲链的适当位置。

可重定位分区分配

  • 引入:因为内存需要,在程序运行前,需要紧凑形成连续空闲区,导致地址错误。
  • 动态重定位实现:装入时任然时相对地址,执行时才进行地址转换(硬件支持,重定位寄存器)。

对换swapping

  • 将内存中暂时不运行的程序和数据,调到外存上。提高内存利用率。
  • 对换空间管理:类似空闲分区表或空闲分区链,不过记录的时对换区的地址与大小,单位是盘块号和盘块数。
  • 进程的换出与换入:换出阻塞状态且优先级最低进程(传送到磁盘对换区,并修改 PCB),换入已换出最久“就绪”状态进程。

基本分页存储管理方式

  • “紧凑”会有较高的开销。减少紧凑操作,所以有离散分配方式。离散分配方式的基本单位不同分成:分页存储管理方式和分段存储管理方式。

页面和页表

  • 页面:将程序的逻辑地址分成若干大小相等的片,称为页面或页,将页进行编号。每页对应内存空间中大小相等的块或页框。分别加以编号。页面大小要适中,否则会页表过大或者,页内碎片过大。
  • 地址结构:程序的逻辑地址:$<页号 31-12, 位移量 11-0>$。所以每页大小最大为 4KB,最多有 1M 页。
  • 页表:内存中记录页号和块号对应关系的表。$<块号>$ 按照页号排序。

地址变换机构

  • 地址变换机构,将逻辑地址变换到内存的物理地址。
  • 块表:具有并行查找能力的高速缓冲寄存器,又称为“联想寄存器”。存放当前访问过的哪些页表项。

两级和多级页表

  • 解决页表需要大的连续内存空间和页表本身需要内存过大的问题
    • 采用离散分配方式解决需要连续大内存空间的问题;
    • 仅将当前需要的部分页表项调入内存,其余存储在磁盘上。
  • 两级页表结构:逻辑地址记录为 $<外层页号 31-22, 外层页内地址, 页内地址>$ 的形式。多级页表类似方式。
  • 增加状态位来表征该页表是否导入内存。不在则产生中断,请求调入内存。

基本分段存储管理方式

  • 为了满足用户在编程和使用上多方面的要求。

分段存储管理方式的引入

  • 方便编程:用户可按照逻辑关系划分若干段,每段地址从 0 开始编址。
  • 信息共享:存放信息的是逻辑单位(而页仅有物理地址的含义,没有完整意义),便于共享。
  • 信息保护:对信息的逻辑单位进行保护。
  • 动态增长:段(特别是数据段)的长度可以不断增加。
  • 动态链接:动态链接也是以段为管理单位的。

分段系统的基本原理

  • 逻辑地址:$<段号 31-16, 段内地址 15-0>$
  • 段表:每个段获得一个连续的内存空间,段表建立每个逻辑段对应的内存位置。段表项:$<段长, 基址>$ 段表存放在段表寄存器中,按照段号排序。
  • 地址变换机构也类似分页系统:但检测越界有两个:段号越界,段长越界(段长是不定的)。对于段表在内存的情况,也配置联想寄存器,改善计算速率。
  • 分页和分段的主要区别:
    • 页是物理单位,目的是提高内存利用率。段是信息的逻辑单位,具有相对的完整的信息,目的是方便用户需求。
    • 页大小固定且由系统决定,页号和页内地址的长度划分也是是机器硬件实现的。段长度却不固定,取决于用户的程序长度。
    • 分页的地址空间是一维的,单一线性空间(因为页面大小是固定的)。段内的空间是二维的,由段号和段内地址共同决定(段长大小不固定)。
  • 可重入代码:允许多个进程同时访问的代码。各进程所执行的代码完全相同,所以不允许执行过程中,对该代码进行任何修改。将数据和程序区进行分离,数据区可改,程序区不可改,使得代码程序区不改动称为可重入代码。

段页式存储管理方式

  • 基本原理:将程序分成若干段,段则分为若干页,每个段赋予一个段名。逻辑结构:$<段号, 段内页号, 页内地址>$。
  • 段页式存储地址变换过程:
    • 段号<段表长度,则段号+段表始址得到段表中的段表项位置
    • 页号<段表项内页表长度,页表始址+页号获得页表中的页表项位置
    • 页表项内的块号+页内地址,获得内存中的物理地址。
  • 高速缓冲寄存器,同时利用段号和页号检索高速缓存。

虚拟存储器的基本概念

  • 引入原因:内存不足存放过大的作业或作业过多无法存储。而且无法增加内存。

虚拟内存的引入

  • 常规存储器管理方式特征:一次性和驻留性。
  • 局部性原理:短时间内,程序的执行局限于某个部分,访问的数据也局限于某个区域。表现在时间局限性(程序和数据的连续访问)和空间局限性(连续访问往往访问被访问单元附近的单元,例如顺序执行)。
  • 虚拟存储器:指具有请求调入功能和置换功能, 能从逻辑上对内存容量加以扩充的一种存储器系统。

虚拟存储器的实现方法

  • 分页请求系统:增加页面请求功能和页面置换功能的页式虚拟存储系统。置换和调入均以页面为单位。
    • 硬件支持:
      1. 请求分页的页表机制:在纯分页的页表机制上增加若干项形成。
      2. 缺页中断机构:程序访问尚未调入内存的页面,则产生中断,将缺页调入内存。
      3. 地址变换机构:在村分页地址变换机构的基础上发展。
    • 请求分页的软件:实现所需页面的调入和暂时不用的页面的置换。
  • 请求分段系统:增加请求调段及分段置换功能的段式虚拟存储系统。
    • 硬件支持:与虚拟分页类似:请求分段的段表机制,缺段中断机构,地址变换机构。
  • 部分芯片支持段页式虚拟存储器。

虚拟存储器的特征

  • 多次性:多次调入内存。
  • 对换性:占不使用的程序和数据(甚至进程亦可)对换出内存。
  • 虚拟性:逻辑上扩充内存容量。

请求分页存储管理方式

由于分页长度固定,所以比请求分段系统简单,所以是最常用的实现虚拟存储器的方式。

请求分页的硬件支持

  • 页表机制:页表项 $<页号, 物理块号, 状态位 P, 访问字段 A, 修改位 M, 外存地址>$
    • 状态位 P:显示程序是否已在内存。
    • 访问字段 A:记录这段时间,被访问次数或多长时间未被访问。
    • 修改位 M:调入内存后是否被修改过。(未修改,则换出时无需写入外存)
    • 外存地址:通常是外存上的物理块号。
  • 缺页中断机构:经历保护 CPU 环境,分析中断原因,转入缺页中断处理程序、恢复 CPU 环境等几个步骤。与一般中断有两个区别:
    • 指令执行期间产生和处理中断信号。在执行指令期间,发现指令或数据不在内存时所产生和处理的。
    • 一条指令在执行期间,可能产生多次缺页中断。
  • 地址变换机构:实现地址变换或缺页请求终端,或越界中断。注意修改快表,访问位/修改位,修改页表,外存等。

内存分配策略和分配算法

  • 最小物理块数的确定:保证系统正常运行的最小物理块数。与硬件结构、指令的格式、功能和寻址方式有关。
  • 物理块的分配策略:
    • 固定分配局部置换:分配的物理块数在分配后不再改变,该进程所需的置换仅在该进程分配到的 n 个块中发生。
    • 可变分配全局置换:空物理块队列由系统维护,缺页时使用该队列的空物理块,没有空物理块则选择一页调出(可为系统中任一进程的页)。
    • 可变分配局部置换:换出仅从该进程的内存页中换出,不影响其他进程。如果该进程频繁缺页中断,则再为其分配若干附加物理块。缺页率低则适当减少物理块。
  • 物理块分配算法:
    • 平均分配算法
    • 按比例分配算法
    • 考虑优先权的分配算法

调页策略

  • 调入页面时机:
    • 预调页策略:预测不久会被访问的页面,预先调入。但一般仅使用与首次调入,由程序员指出先调入哪些页。
    • 请求调页策略:访问到某些程序或数据时,发现不在内存,发起请求,由 OS 将其调入。
  • 确定从何调入页面:
    • 对换区充足,则完全从对换区调入所需页面。(提前将文件区与该进程相关文件拷贝到对换区)
    • 对换区不足,则不会修改文件从文件区调入,需要修改文件从对换区调入(或对换到对换区)。
    • UNIX 方式:未运行过文件从文件区调入,曾经运行过但被换出页面放入对换区(下次则从对换区换入,允许不同程序页面共享)。
  • 页面调入过程

页面置换算法 Page-Replacement Algorithms

最佳置换算法和先进先出置换算法

  • 最佳置换算法:仅是理想中能实现,实际无法预知最佳置换块,所以仅能作为参考用。
  • 先进先出 FIFO 页面置换算法:淘汰最先进入内存的页面。

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

  • 最近的过去作为最近的将来的近似。使用到了页表项中的访问字段 A,淘汰最久未访问的页面。
  • 需要硬件支持(二者选其一即可):
    • 寄存器:为每一个在内存的页面配置移位寄存器,通过移位寄存器值最小则为最久未使用的页面的寄存器。
    • 栈:特殊的栈(不是上进上出),访问存在页时:出被访问的页,从顶部入(保证每次被访问页都在栈顶)。未满时新加入则在栈顶。对换则换出栈底。

Clock置换算法

  • 近似的 LRU 算法
  • 简单的 Clock 置换算法:一位访问位,被访问则置为 1,当需要换出时,检测访问位,为 1 则不换出,置为 0。为 0 则换出。这种算法成为最近未用算法 NRU(Not Recently Used)。
  • 改进的 Clock 置换算法:在简单的 Clock 置换算法基础上考虑置换的代价,有限置换未被修改的页面。减少了 I/O 操作。

其他置换算法

  • 最少使用(LFU:Least Frequently Used)置换算法:采用移位寄存器计数,$\sum{R_i}$ 最小的页是最近一段时间使用最少的页。使用将最高位寄存器置为 1,但每隔一段时间会右移动一次(这个时间可以较长)。
  • 页面缓冲算法:将需要置换出去的已修改的链表放到一个链表的末尾,当达到一定数目的页面时,一次性写回磁盘,减少磁盘的 I/O 操作。

请求分段存储管理方式

  • 硬件支持:
    • 段表机制;
    • 缺断中断机制
    • 地址变换机构
  • 分段的共享和保护

Similar Posts

Comments