操作系统:第三章 内存管理1 - 详解存储管理方式,段表、页表

本文主要是介绍操作系统:第三章 内存管理1 - 详解存储管理方式,段表、页表,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

本文已收录至 Github(MD-Notes),若博客中有图片打不开,可以来我的 Github 仓库:https://github.com/HanquanHq/MD-Notes,涵盖了互联网大厂面试必问的知识点,讲解透彻,长期更新中,欢迎一起学习探讨。
面试必会系列专栏:https://blog.csdn.net/sinat_42483341/category_10300357.html
操作系统系列专栏:https://blog.csdn.net/sinat_42483341/category_10519484.html


第三章 内存管理1 - 存储管理方式,段表、页表详解

目录

  • 第三章 内存管理1 - 存储管理方式,段表、页表详解
  • 第三章 内存管理
    • 基础知识
      • 逻辑地址 / 物理地址
        • 装入的三种方式
          • 1、绝对装入:编译时完成地址变换
          • 2、静态重定位:装入时完成地址变换
          • 3、动态重定位:运行时才进行地址变换表(普遍使用)
        • 从写程序到程序运行
          • 链接的三种方式
    • 内存管理
      • 内存空间的分配与回收
        • 覆盖技术(只用于早期的操作系统)
        • 交换技术
          • 覆盖与交换的区别
        • 连续分配管理方式
          • 单一连续分配
          • 固定分区分配
          • 动态分区分配
          • 动态分区分配算法
        • 非连续分配管理方式
          • 基本分页存储管理
            • 思想
            • 易混
            • 页表(page frame)
            • 逻辑地址结构
            • 如何实现地址转换
            • 基本地址变换机构
            • 具有快表的地址变换机构
            • 两级页表
            • 例题
          • 基本分段存储管理
            • 分段
            • 段表
            • 地址变换
            • 分段、分页管理的对比
          • 段页式存储管理
            • 地址变换
            • 访存次数


第三章 内存管理

基础知识

1 Byte(字节) = 8 bit

1 字 = 16 / 32 / … bit,字由若干个字节构成,不同的机器有不同的字长。

2^10 = 1 K(千)
2^20 = 1 M(兆,百万)
2^30 = 1 G (十亿,百兆)

例如,4 GB = 4 * 2^30 bit = 2^32 bit

逻辑地址 / 物理地址

为了简化理解,本节中我们默认操作系统给进程分配的是一片连续的内存空间

装入的三种方式
1、绝对装入:编译时完成地址变换
  • 编译时,如果知道程序将放到内存中的哪个位置,编译程序 将产生 绝对地址 的目标代码。
  • 装入时,装入程序按照装入模块中的地址,将程序和数据装入内存。

特点:只适用于单道程序环境。

2、静态重定位:装入时完成地址变换
  • 编译、链接后的装入模块的地址都是 从 0 开始逻辑地址
  • 装入时,根据内存的当前情况,对地址进行 重定位,将 逻辑地址 变换为 物理地址

特点:一个作业装入内存时,必须分配其要求的全部内存空间,如果没有足够的内存,就不能装入该作业。作业一旦进入内存,在运行期间不能再移动,也不能再申请内存空间。

3、动态重定位:运行时才进行地址变换表(普遍使用)
  • 编译、链接后的装入模块的地址都是 从 0 开始
  • 执行时,才将 逻辑地址 转换为 物理地址。这种方式需要 重定位寄存器 的支持。

特点:允许程序在内存中发生移动。

从写程序到程序运行

在这里插入图片描述

  1. 编译:由编译程序将用户源代码编译成若干个目标模块(编译就是把高级语言翻译为机器语言)
  2. 链接:由链接程序将编译后形成的一组目标模块,以及所需库函数链接在一起,形成一个完整的装入模块
  3. 装入(装载):由装入程序将装入模块装入内存运行
链接的三种方式
  1. 静态链接:程序运行之前,先将各目标模块及它们所需的库函数连接成一个完整的可执行文件(装入模块),之后不再拆开。
  2. 装入时动态链接:将各目标模块装入内存时,边装入边链接。
  3. 运行时动态链接:在程序执行中需要该目标模块时,才对它进行链接。便于修改、更新、共享模块。

内存管理

内存空间的分配与回收

覆盖技术(只用于早期的操作系统)

思想:将程序分为多个段(多个模块)。常用的段常驻内存,不常用的段在需要时调入内存。

内存中分为一个 固定区 和若干 覆盖区

  • 常驻内存的段放在“固定区”中,运行过程中不再调出
  • 不常用的段放在“覆盖区”,根据需要调入调出

由程序员声明覆盖结构,操作系统完成自动覆盖。对用户不透明,增加了用户编程负担。

在这里插入图片描述

交换技术

内存紧张时,换出某些进程以腾出内存空间,再换入某些进程。进程的 PCB 需要常驻内存。

中级调度 就是要决定将哪个处于挂起状态的进程重新调入内存。

磁盘分为 文件区对换区(swap分区),换出的进程放在对换区。

  • 文件区:离散分配方式,空间利用率高
  • 交换区:连续分配方式,IO 速度快
覆盖与交换的区别

覆盖是在同一个程序 / 进程中的,交换是在不同进程 / 作业间的。

连续分配管理方式

为用户进程分配的必须是一个连续的内存空间

单一连续分配

在这里插入图片描述

支持单道程序,内存分为系统区 / 用户区

  • 系统区:存放操作系统相关数据
  • 用户区:存放用户进程相关数据。内存中只能有一道用户程序,独占整个用户区空间。

无外部碎片,有内部碎片

固定分区分配

支持多道程序,内存用户空间分为若干个固定大小的分区,每个分区只能装一道作业

两种分区方式:分区大小相等 / 分区大小不等

在这里插入图片描述

分区说明表(可用数组 / 链表表示)

在这里插入图片描述

无外部碎片,有内部碎片

动态分区分配

支持多道程序,在程序装入内存时,根据进程的大小动态地建立分区

无内部碎片,有外部碎片

回收内存分区时,可能遇到的四种情况:空间相邻的分区需要合并

  • 回收区之后有相邻的空闲分区
  • 回收区之前有相邻的空闲分区
  • 回收区前后都有相邻的空闲分区
  • 回收区前后都没有相邻的空闲分区
动态分区分配算法

两种常用的数据结构:空闲分区链 / 空闲分区表

在这里插入图片描述

算法算法思想分区排列顺序优点缺点
首次适应从头到尾找适合的分区空闲分区以地址递增次序排列综合看性能最好。算法开销小,回收分区后一般不需要对空闲分区队列重新排序低地址不断划分,产生很多小外部碎片,而每次从低地址开始找,增大了查找开销
最佳适应优先使用更小的分区,以保留更多大分区空闲分区以容量递增次序排列会有更多的大分区被保留下来,更能满足大进程需求会产生很多太小的、难以利用的碎片;算法开销大,回收分区后可能需要对空闲分区队列重新排序
最坏适应优先使用更大的分区,以防止产生太小的不可用的碎片空闲分区以容量递减次序排列可以减少难以利用的小碎片大分区容易被用完,不利于大进程;算法开销大(原因同上)
邻近适应由首次适应演变而来,每次从上次查找结束位置开始查找空闲分区以地址递增次序排列(可排列成循环链表)不用每次都从低地址的小分区开始检索。算法开销小(原因同首次适应算法)会使高地址的大分区先被用完
非连续分配管理方式
基本分页存储管理
思想
  • 把进程分页,各页面放入不同内存块中
易混
  • 页框 = 页帧 = 内存块 = 物理块 = 物理页面**(内存空间划分)** VS 页 = 页面**(进程逻辑空间划分)**
  • 页框号 = 页帧号 = 内存块号 = 物理块号 = 物理页号 VS 页号 = 页面号
  • 页面页框 是一一对应关系,使用 页表 记录这种对应关系
页表(page frame)

在这里插入图片描述

  • 页表记录 页面 -> 内存块 映射关系
  • 一个进程对应一张页表,进程每一页对应一个页表项(页号 + 块号)
  • 页表项的大小相同。页号隐含,不占空间
  • i 号页表项存放地址 = 页表地址 + i * 页表项大小
逻辑地址结构
  • 逻辑地址用 页号、页内偏移量 表示

    • 页号 = 逻辑地址 / 页面大小

    • 页内偏移量 = 逻辑地址 / 页面大小 -> 为何页面大小取 2 的整数次幂?类似于子网掩码方便二进制运算

      假设物理地址也用32个二进制位表示,则由于内存块的大小=页面大小,因此:

      0号内存块的起始物理地址是 00000000000000000000 000000000000
      1号内存块的起始物理地址是 00000000000000000001 000000000000
      2号内存块的起始物理地址是 00000000000000000010 000000000000
      3号内存块的起始物理地址是 00000000000000000011 000000000000

      假设通过查询页表得知1号页面存放的内存块号是9(1001),则9号内存块的起始地址= 9*4096 = 00000000000000001001000000000000,则逻辑地址4097对应的物理地址= 页面在内存中存放的起始地址+ 页内偏移量 =(00000000000000000011000000000001)

      即,如果页面大小刚好是2的整数幂,则只需把页表中记录的物理块号拼接上页内偏移量,就能得到对应的物理地址

如何实现地址转换
  1. 计算出逻辑地址的页号、页内偏移量
  2. 找到对应页面在内存中的存放位置(查页表)
  3. 物理地址 = 页面地址 + 页内偏移量
基本地址变换机构

是用于实现 逻辑地址物理地址 转换的一组硬件机构

页表寄存器存放 页表起始地址、页表长度

地址变换手算过程:

  1. 计算页号、页内偏移量
  2. 比较页号 P 和页表长度 M,若P≥M,则产生越界中断,否则继续执行(页号从0开始)
  3. 页表项地址 = 页表起始地址F + 页号P * 页表项长度,取出该页表项内容b,即为内存块号
  4. 计算E = b * L + W,用得到的物理地址E 去访存(若二进制,可直接拼接)

其他小细节

  • 页内偏移量位数、页面大小之间可以互相计算
  • 页式管理中地址是一维的
  • 实际应用中,通常使一个页框恰好能放入整个页表项
  • 为了方便找到页表项,页表一般是放在连续的内存块中的
具有快表的地址变换机构

快表,又称联想寄存器(TLB, translation lookaside buffer),是一种高速缓存。由于程序的局部性原理,通过存放最近访问的页表项的副本,加快地址变换的速度。

对应地,内存中的页表常称为慢表。

在这里插入图片描述

引入快表前后的地址变换过程:

地址变换过程访问一个逻辑地址的访存次数
基本地址变换机构①算页号、页内偏移量
②检查页号合法性
③查页表,找到页面存放的内存块号
④根据内存块号与页内偏移量得到物理地址
⑤访问目标内存单元
两次访存
具有快表的地址变换机构①算页号、页内偏移量
②检查页号合法性
③查快表。若快表命中,即可知道页面存放的内存块号,可直接进行⑤;若未命中,则进行④
④查页表,找到页面存放的内存块号,并且将页表项复制到快表中
⑤根据内存块号与页内偏移量得到物理地址
⑥访问目标内存单元
快表命中,只需一次访存;快表未命中,需要两次访存
两级页表

单级页表存在的问题:

  • 所有页表项必须连续存放,页表过大时需要很大的连续空间
  • 在一段时间内并非所有页面都用得到,因此没必要让整个页表常驻内存

两级页表:

  • 将长长的页表再分页
  • 逻辑地址结构:一级页号 / 二级页号 / 页内偏移量
  • 注意几个术语:页目录表 / 外层页表 / 顶级页表

如何实现地址变换:

  • 按照地址结构将逻辑地址拆分成三份
  • 从 PCB 中读出页目录表起始地址,根据一级页号查询页目录表,找到下一级页表在内存中的存放位置
  • 根据二级页表查表,找到最终想访问的内存号
  • 结合业内偏移量得到物理地址

几个细节

  • 多级页表中,各级页表的大小不能超过一个页面,若两级页表不够,可以分更多级
  • 多级页表的访问次数(假设没有快表机构):N 级页表访问一个逻辑地址需要 N+1 次访存
例题

在这里插入图片描述

基本分段存储管理
分段

以段为单位进行分配,段内连续,段间可不相邻。

在这里插入图片描述

分段系统的逻辑地址结构由段号(段名)和段内地址(段内偏移量)所组成。

  • 段号的位数 决定了每个进程最多可以分几个段
  • 段内地址位数 决定了每个段的最大长度是多少
段表

为了能从物理内存中找到各个逻辑段的存放位置,需为每个进程建立一张段映射表,称 段表

各个段表项的长度是相同的。因此段号是隐含的,不占存储空间。

在这里插入图片描述

地址变换
  1. 根据逻辑地址得到段号、段内地址
  2. 判断 段号是否越界。若 S ≥ M,则产生越界中断(段表长度至少是1,而段号从0开始)
  3. 查询段表,找到对应的段表项,段表项的存放地址 = F + S * 段表项长度
  4. 检查 段内地址是否超过段长(因为段长各不相同)。若 W ≥ C,则产生越界中断
  5. 计算得到物理地址
  6. 访问目标内存单元
分段、分页管理的对比
  • 页是物理单位。分页是系统管理,对用户不可见;地址空间是一维的。
  • 段是逻辑单位。分段是用户需求,需要程序员指出段名。地址空间是二维的(段名 + 段内地址)

注:分段存储也可以引入快表机构。

段页式存储管理
优点缺点
分页管理内存空间利用率高,不会产生外部碎片,只有少量页内碎片不方便按照逻辑模块实现信息的共享和保护
分段管理方便按照逻辑模块实现信息共享 / 保护如果段长过大,为其分配很大的连续空间会很不方便。段式管理会产生外部碎片。

段页式系统的逻辑地址结构由段号、页号、页内地址(页内偏移量)组成。

“分段”对用户是可见的,程序员编程时需要显式地给出段号、段内地址。而将各段“分页”对用户是不可见的。系统会根据段内地址自动划分页号和页内偏移量。因此段页式管理的地址结构是二维的。

  • 段号的位数决定了每个进程最多可以分几个段
  • 页号位数决定了每个段最大有多少页
  • 页内偏移量决定了页面大小、内存块大小是多少

在这里插入图片描述

地址变换
  1. 由逻辑地址得到段号、页号、页内偏移量
  2. 段号与段表寄存器中的段长度比较,检查是否越界
  3. 由段表起始地址、段号,找到对应的段表项
  4. 根据段表中记录的页表长度,检查页号是否越界
  5. 由段表中的页表地址、页号得到查询页表,找到相应页表项
  6. 由页面存放的内存块号、页内偏移量,得到最终物理地址
  7. 访问目标单元
访存次数

3 次访存。查段表、查页表、访问目标单元。可引入快表机构,由(段号+页号)直接找到目标地址,只需要一次访存。

这篇关于操作系统:第三章 内存管理1 - 详解存储管理方式,段表、页表的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/557043

相关文章

Spring Security基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

NameNode内存生产配置

Hadoop2.x 系列,配置 NameNode 内存 NameNode 内存默认 2000m ,如果服务器内存 4G , NameNode 内存可以配置 3g 。在 hadoop-env.sh 文件中配置如下。 HADOOP_NAMENODE_OPTS=-Xmx3072m Hadoop3.x 系列,配置 Nam

综合安防管理平台LntonAIServer视频监控汇聚抖动检测算法优势

LntonAIServer视频质量诊断功能中的抖动检测是一个专门针对视频稳定性进行分析的功能。抖动通常是指视频帧之间的不必要运动,这种运动可能是由于摄像机的移动、传输中的错误或编解码问题导致的。抖动检测对于确保视频内容的平滑性和观看体验至关重要。 优势 1. 提高图像质量 - 清晰度提升:减少抖动,提高图像的清晰度和细节表现力,使得监控画面更加真实可信。 - 细节增强:在低光条件下,抖

OpenHarmony鸿蒙开发( Beta5.0)无感配网详解

1、简介 无感配网是指在设备联网过程中无需输入热点相关账号信息,即可快速实现设备配网,是一种兼顾高效性、可靠性和安全性的配网方式。 2、配网原理 2.1 通信原理 手机和智能设备之间的信息传递,利用特有的NAN协议实现。利用手机和智能设备之间的WiFi 感知订阅、发布能力,实现了数字管家应用和设备之间的发现。在完成设备间的认证和响应后,即可发送相关配网数据。同时还支持与常规Sof

内核启动时减少log的方式

内核引导选项 内核引导选项大体上可以分为两类:一类与设备无关、另一类与设备有关。与设备有关的引导选项多如牛毛,需要你自己阅读内核中的相应驱动程序源码以获取其能够接受的引导选项。比如,如果你想知道可以向 AHA1542 SCSI 驱动程序传递哪些引导选项,那么就查看 drivers/scsi/aha1542.c 文件,一般在前面 100 行注释里就可以找到所接受的引导选项说明。大多数选项是通过"_

软考系统规划与管理师考试证书含金量高吗?

2024年软考系统规划与管理师考试报名时间节点: 报名时间:2024年上半年软考将于3月中旬陆续开始报名 考试时间:上半年5月25日到28日,下半年11月9日到12日 分数线:所有科目成绩均须达到45分以上(包括45分)方可通过考试 成绩查询:可在“中国计算机技术职业资格网”上查询软考成绩 出成绩时间:预计在11月左右 证书领取时间:一般在考试成绩公布后3~4个月,各地领取时间有所不同

安全管理体系化的智慧油站开源了。

AI视频监控平台简介 AI视频监控平台是一款功能强大且简单易用的实时算法视频监控系统。它的愿景是最底层打通各大芯片厂商相互间的壁垒,省去繁琐重复的适配流程,实现芯片、算法、应用的全流程组合,从而大大减少企业级应用约95%的开发成本。用户只需在界面上进行简单的操作,就可以实现全视频的接入及布控。摄像头管理模块用于多种终端设备、智能设备的接入及管理。平台支持包括摄像头等终端感知设备接入,为整个平台提

6.1.数据结构-c/c++堆详解下篇(堆排序,TopK问题)

上篇:6.1.数据结构-c/c++模拟实现堆上篇(向下,上调整算法,建堆,增删数据)-CSDN博客 本章重点 1.使用堆来完成堆排序 2.使用堆解决TopK问题 目录 一.堆排序 1.1 思路 1.2 代码 1.3 简单测试 二.TopK问题 2.1 思路(求最小): 2.2 C语言代码(手写堆) 2.3 C++代码(使用优先级队列 priority_queue)

用命令行的方式启动.netcore webapi

用命令行的方式启动.netcore web项目 进入指定的项目文件夹,比如我发布后的代码放在下面文件夹中 在此地址栏中输入“cmd”,打开命令提示符,进入到发布代码目录 命令行启动.netcore项目的命令为:  dotnet 项目启动文件.dll --urls="http://*:对外端口" --ip="本机ip" --port=项目内部端口 例: dotnet Imagine.M

K8S(Kubernetes)开源的容器编排平台安装步骤详解

K8S(Kubernetes)是一个开源的容器编排平台,用于自动化部署、扩展和管理容器化应用程序。以下是K8S容器编排平台的安装步骤、使用方式及特点的概述: 安装步骤: 安装Docker:K8S需要基于Docker来运行容器化应用程序。首先要在所有节点上安装Docker引擎。 安装Kubernetes Master:在集群中选择一台主机作为Master节点,安装K8S的控制平面组件,如AP