当前位置: 首页 > news >正文

操作系统—第三章 内存管理

3.1内存管理概念

操作系统对内存的划分和动态分配

主要功能:

  • 内存空间的分配与回收
  • 地址变换:将逻辑地址转换成相应的物理地址
  • 内存空间的扩充:利用虚拟存储技术从逻辑上扩充内存
  • 内存共享:允许多个进程访问内存的同一部分
  • 存储保护:保证各个进程在各自的存储空间内运行,互不干扰

逻辑地址与物理地址

1.相对地址(逻辑地址)

指每个模块都从0号开始编址,不同进程可以拥有相同的逻辑地址,这些相同的逻辑地址可以映射到主存的不同位置

链接程序:将各个模块链接成一个完整的可执行目标程序,顺序依次给各个模块相对地址构成统一的从0号单元开始编址的逻辑地址空间(虚拟地址空间)

2.物理地址空间:

内存中物理单元的集合,是地址转换的最终地址

当装入程序将可执行代码装入内存时,必须通过地址转换将逻辑地址转换成物理地址,这个过程称为地址重定位

3.内存管理部件MMU

将进程使用的逻辑地址转换为物理地址

程序的链接与装入

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

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

在这里插入图片描述

程序的装入

将一个装入模块装入内存时,有以下三种装入方式

1.绝对装入

  • 只适用于单道程序环境
  • 知道程序将放到内存的哪个位置,编译程序产生绝对地址的目标代码
  • 程序中的逻辑地址与实际内存地址完全相同

2.可重定位装入(静态重定位)

  • 装入时对目标程序中的相对地址的修改过程称为重定位
  • 只能对程序中的地址进行一次修改,而不能动态调整
  • 必须分配连续内存空间

3.动态运行时装入(动态重定位

  • 将地址转换推迟到程序真正要执行时才进行,装入内存后的所有地址均为相对地址

  • 这种方式需要:

    • 重定位寄存器(也称基址寄存器),存放进程的基地址,整个系统中只设置一个
    • 可重定位装入程序,在重定位的过程中执行
    • 地址变换机构,将指令中的逻辑地址与重定位寄存器中的基地址相加得到物理地址
  • 优点:

    • 可以将程序分配到不连续的存储器;
    • 根据需要动态申请分配内存;
    • 便于程序段的共享
    • 能保证一个程序在主存中被改变存放位置后仍能正常执行

程序的链接

1.静态链接

在程序运行之前,先将个目标模块及它们所需的库函数链接成一个完整的装入模块,以后不再拆开

2.装入时动态链接

再装入模块时,采用边装入边链接的方式

优点:便于修改和更新,便于实现对目标模块的共享(“目标模块的共享”指的是在多个程序或模块之间复用同一个目标文件(编译产物),或者在运行时多个程序共享同一段目标模块的代码和数据,以提高效率、节省资源。)

3.运行时动态链接

在程序执行中需要某目标模块时,才对它进行链接

优点:能加快程序的装入过程,还可节省空间

进程的内存映射

当一个程序调入内存运行时,就构成了进程的内存映射,一个进程的内存映射一般有几个要素:

  • 代码段
  • 数据段
  • 进程控制块PCB

内存保护

确保每个进程都有一个单独的内存空间,需要由操作系统和硬件机构合作完成

上下限地址保护

在CPU中设置一对上下限寄存器,存放用户进程在主存中的下限和上限地址

界地址保护

采用重定位寄存器(也称基地址寄存器)和界地址寄存器(也称限长寄存器)进行越界检查

  • 重定位寄存器存放进程的起始物理地址
  • 界地址寄存器存放进程最大逻辑地址

内存管理部件MMU将逻辑地址与界地址寄存器进行比较,未越界则加上重定位寄存器的值后映射成物理地址

内存共享

只有只读的区域才可以共享

可重入代码(纯代码)

允许多个进程同时访问但不允许被任何进程修改的代码

**最大的优点:**减少了对程序段的调入/调出,减少了对换数量

数据区

将在执行中可能改变的部分复制到数据区,程序在执行时只需对该私有数据区中的内存进行修改,并不去改变共享的代码

连续分配方式

指为一个用户程序分配一个连续的内存空间,主要包括:

1.单一连续分配

内存被分为系统区和用户区

  • 系统区仅供操作系统使用,通常在低地址部分
  • 用户区内存中仅有一道程序,即用户程序独占整个用户区

**优点:**简单、五外部碎片;不需要进行内存保护

**缺点:**只能用于单用户、单任务的操作系统中;有内部碎片;内存的利用率极低

2.固定分区分配

最简单的一种多道程序存储管理方式,将用户内存空间提前划分为若干固定大小的分区,每个分区只装入一道作业

  • 分区大小相等
  • 分区大小不等

**优点:**无外部碎片

缺点:内存的利用率低,并存在两个问题①程序太大而放不进任何一个分区②程序小于固定分区大小也要占用一个完整的内存分区,存在空间浪费,这种现象称为内部碎片

3.动态分区分配(可变分区分配)

基本原理

根据进程的实际需要,动态地为之分配内存,

随着时间的推移,内存中会产生越来越多的小内存块,内存的利用率也随之下降,这些小内存块被称为外部碎片

虽然动态分区分配分配的是连续的物理空间,但每个进程仍使用从 0 开始的逻辑地址空间,所以仍需要硬件地址变换机构(基址 + 限长寄存器)来把逻辑地址转为物理地址,并实现内存保护。

内存回收

设这一张空闲分区链表,可以按始址排序

若有相邻的空闲分区,则合并两个分区,并修改为一个分区表项

若没有相邻的空闲分区,为回收区新建一个表项,插入空闲分区链

基于顺序搜索的分配算法

依次搜索空闲分区链上的空闲分区,以寻找一个大小满足要求的分区

  • 首次适应算法:空闲分区按地址递增的次序排列,每次顺序找到第一个能满足大小
  • 邻近适应算法(循环适应算法):按地址递增排序,分配内存时从上次查找结束的位置开始继续查找
  • 最佳适应算法:空闲分区按容量递增的次序排序,每次顺序找到能满足大小的最小空闲分区分配给作业
  • 最坏适应算法:空闲分区按容量递减的次序排序,每次从最大的空闲分区中分割一部分空间给作业

首次适应算法开销小,性能最好,回收分区也不需要对空闲分区重新排序

基于索引搜索的分配算法

思想:对于每类大小相同的空闲分区,单独设立一个空闲分区链,并设置一张索引表来管理这些空闲分区链。当为进程分配空间时,在索引表中查找所需空间大小对应的表项。在大、中型系统中往往采用索引分配算法

  • 快速适应算法:首先从索引表中找到能容纳它的最小空闲分区链表,然后从链表中取下第一块进行分配
    • **优点:**查找效率高、不会产生内存碎片
    • **缺点:**回收内存时,需要有效地合并分区,算法复杂,系统开销大
  • 伙伴系统:所有分区的大小均为2的k次幂,当需要大小为n的分区时(2i−1<n≤2i2^{i-1}<n≤2^i2i1n2i),从大小为2i2^i2i开始往更大的的空闲分区链找,若找到的空闲分区链不是2i2^i2i,则将其等分开为两个分区,分区称为一对伙伴,其中一个用于分配,而将另一个加入大小为2i2^i2i的空闲分区链,回收时需要需要将相邻的空闲伙伴分区合并成更大的分区
  • 哈希算法:构造一张以空闲分区大小为关键字的哈希表

基本分页存储管理(固定分区大小的非连续分配方式)

思想:将内存空间分为若干固定大小(如4KB)的分区,称为页框(也称为页帧或物理块)

如果知道主存大小和页框数量,则页框大小=主存大小/页框数量

进程的逻辑地址空间也分为与块大小相等的若干区域,称为(也称为页面

操作系统以页框为单位分配内存空间

**优点:**不产生外部碎片;进程只会在最后一个不完整的块申请一个主存块空间时,才产生主存碎片(主要是页内碎片)

块的大小相对分区要小很多,产生的内存碎片(也称页内碎片)相对进程很小

基本概念

页面和页面大小:

  • 进程的逻辑地址空间中的每个页面有一个编号,称为页号,从0开始

  • 内存空间中的每个页框也有一个编号,称为页框号(或物理块号),从0开始

  • 要为每个页面分配内存中的可用页框

地址结构:

  • 包含两部分:前一部分为页号,后一部分为页内偏移量

在这里插入图片描述

页号的位数表示了最多允许有多少页,也指一页可以存放多少个页表项

页内偏移量位数表示了每页大小

整个位数表示了主存的最大容量

页表(页面映射表):

  • 每个进程有一个页表,用于将它的逻辑地址空间映射到物理地址空间
  • 进程的每个页面对应一个页表项,每个页表项由页号和块号组成,记录了页面在内存中对应的物理块号
  • 页表的作用是实现从页号到物理块号的地址映射
  • 驻留在内存中

基本地址变换机构

地址变换机构的任务是将逻辑地址转换为内存中的物理地址

系统之设置一个页表寄存器(PTR),存放页表在内存的始址F和页表长度M

查找页表的工作是由硬件自动完成的

变换过程:

  1. 计算页号P=逻辑地址A/页面大小L,页内偏移量W=A%L
  2. 若页号P≥页表长度M,则越界中断
  3. 页号P对应的页表项地址=页表始址F+页号P*页表项长度,查出物理块号(或页框号)b
  4. 计算物理地址E=bL+W

在这里插入图片描述

具有快表的地址变换机构

**快表(TLB,也称相联存储器):**用来存放当前访问的若干页表项,以加快地址变换过程

主存中的页表称为慢表

变换过程:

  • 将页号与快表中的所有页号进行比较,若找到读取物理块号,存取数据仅一次访存
  • 若未找到,则要访问内存中的页表,并找到页表项后存入快表,存取数据需要两次访存

一般快表的命中率可达90%以上,快表的有效性基于著名的局部性原理

两级页表

进程在执行时不需要将所有页调入内存页框,也不应该将所有页表项都调入内存

解决页表内存大且需要连续的问题:①采用离散分配方式②只将部分页表项调入内存

**外层页表(也称页目录):**为离散分配的页表再建立一张页表

需要在系统中增设一个外层页表寄存器(也称页目录基址寄存器),用于存放页目录始址

基本分段存储管理(不固定分区大小的非连续分配方式)

思想:每个段的长度不固定,根据实际需求动态分配,需要多少内存操作系统就分配多少内存

**优点:**不会产生内部碎片

**主要目的:**满足用户方便编程、分段共享、分段保护、动态链接、动态增长

基本概念

分段:

  • 用户编程时决定
  • 分段把程序按逻辑模块划分,有利于程序的动态链接
    • 动态链接是指:程序运行时,才将某些模块或库装入内存并连接,而不是在编译时就全部链接好。
  • 分段存储管理的逻辑地址由段号S与段内偏移量W两部分组成

段表:

  • 每个进程都有一张逻辑地址与内存空间映射的段表
  • 每个段表项对应进程中的一段
  • 段表项记录了该段在内存中的始址和段的长度
  • 系统提供用户的物理地址空间大小=总空间大小-段表长度

地址变换机构

系统中设置一个段表寄存器,用于存放段表始址F和段表长度M

变换过程:

  1. 从逻辑地址A中取出段号S和段内偏移量W
  2. 若段号S≥段表长度M,则越界中断
  3. 段号P对应的段表项地址=段表始址F+段号P*段表项长度,取出段长C
  4. 若段内偏移量W≥段长C,则越界中断
  5. 取出该段表项的该段始址b
  6. 计算物理地址E=b+W

在这里插入图片描述

段的共享与保护

共享段表,所有共享的段都占一个表项,用来实现多个进程共享一段代码或数据

共享计数器count记录有多少进程正在共享该段,为0才回收该段所占的内存区

每个进程用自己进程的段号去访问该共享段

分页和分段的区别

  • 页是信息的物理单位,分页的主要目的是提高内存利用率,是系统行为用户不可见
  • 段时信息的逻辑单位,分段的主要目的时更好地满足用户需求,用户可见
  • 页的大小固定且系统决定,段的大小不固定用户决定
  • 分页管理的地址空间是一维的,分段管理的地址空间是二维的

段页式存储管理

分页能提高内存效率,分段能有利于共享和保护

段页式中进程的地址空间分为若干逻辑段,然后将各段分成若干大小固定的页

对内存的分配以物理块为单位

**实现原理:**用分段方法来分配和管理用户地址空间,用分页方法来管理物理存储空间

地址变换

  1. 通过段表查到页表始址
  2. 通过页表找到物理块号
  3. 形成物理地址

在这里插入图片描述

3.2虚拟内存管理

基本概念

传统存储器管理方式共同的特征:

  • 一次性:全部装入内存后才能开始运行
  • 驻留性

局部性原理

**高速缓存技术:**快表、页高速缓存、虚拟内存技术

  • 时间局部性:某条指令一旦执行,不久后可能再次执行
  • 空间局部性:某个存储单元被访问,不久后附近存储单元也将被访问

虚拟存储器的定义和特征

特点:

  • 部分装入:仅将程序当前运行要用到的少数页面或段装入内存,而将其余部分留在外存
  • 请求调页/段:当所访问的信息不在内存时,操作系统负责将所需信息从外存调入内存
  • 页面置换(段置换):当内存空间不够时,操作系统负责将内存中暂时用不到的信息换出到外存

特征:

  • 多次性:只将当前要运行的那部分程序和数据装入内存(虚拟存储器最重要的特征
  • 对换性:将暂不使用的程序和数据调出内存
  • 虚拟性:逻辑上扩充内存容量

虚拟内存技术的实现

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

**硬件支持:**内存、外存、页/段表机制、中断机构、地址变换机构

请求分页管理方式

为了实现请求分页,还需要页表机制、缺页中断机制、地址变换机构

1.页表机制

在这里插入图片描述

  • 状态位P:标记该页是否已调入内存
  • 访问字段A:记录本页一段时间的访问量/多久时间未被访问
  • 修改位M:标记该页是否被修改过
  • 外存地址:记录该页都的外存地址

2.缺页中断机制

每当要访问的页面不在内存时,便产生一个缺页中断

3.地址变换机构

增加了产生和处理缺页中断,及从内存中换出一页的功能

页框分配

对于分页式的虚拟内存,操作系统需要决定都多少页,即决定给特定的进程分配几个页框

**驻留集:**给一个进程分配的页框的集合

内存分配策略

  • 固定分配:系统一开始就给每个进程固定数量的页框,在运行过程中不再改变。
  • 可变分配:系统在运行时可以根据实际情况(如缺页频率、进程状态)动态调整某个进程所拥有的页框数量
  • 局部置换:当进程发生缺页时,只允许从该进程自身的页框中选择一页淘汰
  • 全局置换:当进程发生缺页时,可以从所有进程的页框中任选一页进行淘汰,不局限于本进程。

固定分配 + 局部置换

  • 最常见的组合
  • 每个进程分配固定页框,只能替换自己
  • 📌 优点:简单、进程间互不干扰
  • 📌 缺点:某些进程页不够用频繁缺页,另一些进程页框可能被浪费

可变分配 + 局部置换

  • 系统根据运行情况动态调整页框数
  • 缺页时仍然只替换本进程的页
  • 📌 优点:兼顾稳定性和效率,可结合工作集模型动态调整页框分配

可变分配 + 全局置换

  • 页框数量可变,置换时可以选其他进程的页淘汰
  • 📌 优点:全局命中率高,适合负载变化大的系统
  • 📌 缺点:进程间存在强干扰,容易产生抖动(Thrashing)

为什么没有“固定分配 + 全局置换”?

  • 固定分配要求进程页框数量固定不可变
  • 全局置换意味着页框会被别的进程抢走,页框数变了 ➜ 和“固定”矛盾

📌 所以“固定分配 + 全局置换”逻辑上冲突,不存在

物理块调入算法

  • 平均分配算法
  • 按比例分配算法:按照进程大小按比例
  • 优先权分配算法:重要紧迫的进程分配多

调入页面的时机

  • 预调页策略:预测之后可能被访问的页面,将它们预先调入内存
  • 请求调页策略:进程在运行中需要访问的页面不在内存,提出请求

从何处调入页面

  • 系统拥有足够的对换区空间:文件全部存放对换区
  • 系统缺少足够的对换区空间:将不会被修改的文件放文件区,可能被修改的部分换出时放在对换区
  • UNIX方式:曾今运行过但被换出的页面放在对换区

页面置换算法

1.最佳置换算法(OPT)

选择淘汰以后永远不使用的页面,或是在最长时间内不再被访问的页面

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

选择淘汰最早进入内存的页面

Belady异常:分配的物理块增多,缺页次数不减反增的异常现象,只有FIFO算法可能出现

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

选择淘汰最近最长时间未使用的页面

该算法为每个页面设置一个访问字段,记录页面自上次被访问所经历的时间

4.时钟置换算法(CLOCK)

(1)简单的CLOCK置换算法(也称最久未用算法(NRU))


文章转载自:
http://abstrusity.ciuzn.cn
http://centrifugal.ciuzn.cn
http://cesium.ciuzn.cn
http://cartop.ciuzn.cn
http://chirimoya.ciuzn.cn
http://cannibalistic.ciuzn.cn
http://aslant.ciuzn.cn
http://cantilena.ciuzn.cn
http://chileanize.ciuzn.cn
http://belligerency.ciuzn.cn
http://attestant.ciuzn.cn
http://beatific.ciuzn.cn
http://bowline.ciuzn.cn
http://blacklist.ciuzn.cn
http://acquittal.ciuzn.cn
http://attachment.ciuzn.cn
http://bujumbura.ciuzn.cn
http://alluvion.ciuzn.cn
http://caitiff.ciuzn.cn
http://absenteeism.ciuzn.cn
http://bourbonism.ciuzn.cn
http://alec.ciuzn.cn
http://chronologize.ciuzn.cn
http://bam.ciuzn.cn
http://blemya.ciuzn.cn
http://carouser.ciuzn.cn
http://chronological.ciuzn.cn
http://assemblage.ciuzn.cn
http://bluet.ciuzn.cn
http://bacteriostasis.ciuzn.cn
http://www.dtcms.com/a/276615.html

相关文章:

  • 169. 多数元素
  • 二分搜索 (左程云)
  • 【Docker基础】Dockerfile核心概念解析:什么是Dockerfile?与镜像、容器的关系
  • shiro550反序列化漏洞复现(附带docker源)
  • AV1比特流结构
  • zynq-PS篇——bperez77中DMA驱动注意事项
  • 车载以太网-旁路配置
  • MyBatis基于XML配置详细使用指南
  • IMU姿态传感器
  • 栈题解——最小栈【LeetCode】
  • 学历一般,基础一般还有必要刷算法题吗
  • 一种Φ325海底管道机械三通结构设计cad【1张】三维图+设计说明书
  • python学习笔记【1】对字符串的处理
  • 网络安全day1-2笔记
  • kettle从入门到精通 第101课 ETL之kettle DolphinScheduler调度kettle
  • RAG进阶之术:用“父子Chunk”策略破解复杂查询的“上下文迷局”
  • Win11怎样进入WinRE恢复环境
  • 并发--Callable vs Runnable
  • 深入理解 Boost.Asio 中的异步核心 boost::asio::io_context
  • AI智能体|扣子(Coze)搭建【裸眼3D著名故事动画视频】工作流
  • NOIP普及组|2005T1淘淘摘苹果
  • 常用控件QWidget
  • 部署Harbor私有仓库
  • 第五章 RAG知识库进阶
  • Java项目2——增强版飞机大战游戏
  • Linux:信号
  • Redis持久化机制:RDB和AOF
  • 【面试八股文】2025最新软件测试面试
  • 多模态数据解压-Parquet
  • 【数据结构初阶】--顺序表(三)