计算机操作系统(十七)内存管理

计算机操作系统(十七)内存管理

  • 前言
  • 一、内存的使用与程序重定位
    • (一)内存是什么?
    • (二)程序的重定位过程
    • (三)总结:内存使用的核心问题
  • 二、连续分区管理:早期的内存管理方案
    • (一)什么是连续分区?
    • (二)三种典型方案
    • (三)连续分区的致命缺陷:内存碎片
  • 三、分页管理:用"拆分成小块"解决碎片问题
    • (一)核心思想:把内存和程序都切成小块
    • (二)分页的优点
    • (三)分页的问题
  • 四、分段管理:从"逻辑模块"角度管理内存
    • (一)为什么需要分段?
    • (二)分段的核心概念
    • (三)分段的优点
    • (四)分段的缺点
  • 五、段页式管理:集大成者
    • (一)设计思想:分段+分页,取长补短
    • (二)地址转换过程(稍微复杂,但更灵活)
    • (三)优缺点
    • (四)实际应用


前言

  • 在上一篇博客中,我们深入探讨了进程同步,了解了进程间如何协调以避免冲突、有序执行。
  • 进程运行离不开内存资源因此,这一篇博客,我们将开启内存管理的学习之旅,探究操作系统是如何高效管理内存,为进程运行保驾护航的

我的个人主页,欢迎来阅读我的其他文章
https://blog.csdn.net/2402_83322742?spm=1011.2415.3001.5343
我的操作系统博客专栏
https://blog.csdn.net/2402_83322742/category_12916780.html?spm=1001.2014.3001.5482


一、内存的使用与程序重定位

在这里插入图片描述

(一)内存是什么?

内存是计算机中用于临时存储数据和程序的硬件设备,就像我们日常办公时的"书桌"。当我们要运行一个程序(比如打开浏览器),计算机需要先把程序从硬盘(相当于"文件柜")复制到内存这个"书桌"上,CPU才能快速读取并执行。

(二)程序的重定位过程

  1. 程序的三种地址形态

    • 逻辑地址:程序员写代码时用的"虚拟地址",比如在C语言中定义int a=10;,编译器会给变量a分配一个逻辑地址(例如0x1000),这个地址不考虑实际内存位置。
    • 相对地址:经过汇编或编译后生成的"相对起始地址"。比如一个程序模块的相对地址从0开始,内部函数调用使用相对地址(如调用偏移量100的函数)。
    • 物理地址:内存中真实的硬件地址,就像每个内存单元的"门牌号"(例如0x80000010)。
  2. 为什么需要重定位?
    当程序被装入内存时,它在内存中的起始位置是不确定的。比如同一个程序第一次从内存地址0x1000开始存放,第二次可能从0x5000开始。这时候程序内部的逻辑地址必须转换成对应的物理地址,否则CPU会找不到正确的数据,就像快递地址写错会导致包裹送错地方。

  3. 两种重定位方式

    • 静态重定位:在程序装入内存时一次性完成地址转换。就像搬家前把所有家具的位置在图纸上标好,搬家时直接按图纸摆放,之后不再改变。优点是简单,缺点是程序一旦装入就不能移动位置。
    • 动态重定位:程序运行时通过硬件地址转换机构(如基址寄存器)实时转换地址。就像随身携带一个"地址翻译器",走到哪里都能把逻辑地址翻译成当前位置的物理地址。优点是程序可以在内存中移动(比如内存紧凑时),缺点是需要额外的硬件支持。

(三)总结:内存使用的核心问题

程序要在内存中运行,必须解决"地址转换"的问题,而重定位就是连接逻辑世界(程序员视角)和物理世界(硬件视角)的桥梁。

二、连续分区管理:早期的内存管理方案

(一)什么是连续分区?

  • 把内存划分为若干个连续的区域,每个区域分配给一个程序使用,就像把一块大蛋糕切成若干块,每块给一个人吃。
  • 早期的操作系统(如DOS)常用这种方式。

(二)三种典型方案

  1. 单一连续分区(最简单的方案)

    • 内存分为两部分:一部分给操作系统(比如Windows的内核),剩下的全部给一个应用程序。
    • 缺点:一次只能运行一个程序(想想看,你不能同时打开微信和浏览器),内存利用率极低。
  2. 固定分区(稍微进步一点)

    • 提前把内存划分为大小固定的几个分区(比如1MB、2MB、4MB),每个分区可以存放一个程序。
    • 问题:如果程序大小超过分区大小,无法装入;如果程序太小,分区剩余空间浪费(比如一个500KB的程序装入1MB的分区,浪费500KB)。
  3. 动态分区(按需分配)

    • 不再提前划分分区,而是根据程序需要动态划分。比如程序需要3MB内存,就从空闲内存中切出3MB的连续空间。
    • 关键问题:如何高效分配和回收空间?
      • 分配算法
        • 首次适应:从内存起始位置开始找,第一个足够大的空闲块就分配,简单但可能留下小碎片。
        • 最佳适应:找最接近程序大小的空闲块,看似合理,却容易产生大量微小碎片(比如把大空闲块切成刚好够用的小块,剩下的小碎片难以利用)。
      • 回收问题:当程序运行结束释放内存时,如果相邻的空闲块,需要合并成一个大的空闲块,否则会形成不连续的碎片。

(三)连续分区的致命缺陷:内存碎片

无论是固定分区还是动态分区,都会面临"碎片问题"。比如内存中有多个小的空闲块,但合起来不够一个程序使用(就像钱包里有很多零钱,但凑不出一张整钞)。为了解决这个问题,操作系统不得不定期进行"内存紧凑"(把正在运行的程序移动到连续的区域,合并空闲块),但这会消耗大量CPU资源。

三、分页管理:用"拆分成小块"解决碎片问题

(一)核心思想:把内存和程序都切成小块

  1. 页与页框

    • 把程序逻辑地址空间划分为大小相等的"页"(Page,比如4KB大小)。
    • 把物理内存划分为同样大小的"页框"(Page Frame,也叫页帧)。
    • 程序的每个页可以装入任意一个页框,不需要连续,就像把一本书拆分成若干章节(页),每个章节可以放在不同的书架格子(页框)里,只要知道每个章节放在哪个格子,就能快速找到。
  2. 页表:记录"页"的位置

    • 每个程序有一张"页表",记录逻辑页号到物理页框号的映射关系。比如逻辑页0对应物理页框5,逻辑页1对应物理页框3。
    • 地址转换过程:当程序访问逻辑地址(由页号+页内偏移组成),CPU通过页表找到对应的页框号,再加上页内偏移,得到物理地址。例如:页大小4KB(12位),逻辑地址0x1234(二进制0001 0010 0011 0100),前4位(0001)是页号,后12位(0010 0011 0100)是页内偏移。通过页表查到页号1对应的页框号是3(二进制0011),物理地址就是0011 0010 0011 0100(0x3234)。

(二)分页的优点

  1. 几乎消除外部碎片:程序的页可以分散存储,只要有足够的页框就能装入,不会因为空闲块不连续而无法分配。
  2. 内存利用率高:页的大小固定(通常4KB-8KB),每个程序最后一个页即使没装满,浪费的空间也很小(最多一个页的大小),这叫"内部碎片",比连续分区的碎片问题好很多。

(三)分页的问题

  1. 页表占用内存:每个程序都需要页表,如果页表很大(比如64位系统),可能需要多级页表(比如二级页表、三级页表)来减少内存占用。
  2. 程序员无感知:分页是操作系统底层的机制,程序员不需要关心,所有地址转换由硬件和操作系统自动完成。

四、分段管理:从"逻辑模块"角度管理内存

(一)为什么需要分段?

分页解决了内存碎片问题,但它是从"物理内存划分"的角度设计的,而程序员写程序时更习惯按逻辑模块划分(比如代码段、数据段、堆栈段)。比如一个C程序包含main函数(代码段)、全局变量(数据段)、函数调用栈(堆栈段),分段管理就是把这些逻辑模块分别装入内存,每个段可以独立增长和共享。

(二)分段的核心概念

  1. :每个程序由若干个段组成,每个段有自己的名称(如代码段.text、数据段.data)和长度。比如代码段可能有10KB,数据段可能有5KB。
  2. 段表:记录每个段的起始物理地址和长度。当程序访问逻辑地址(段号+段内偏移),首先检查段内偏移是否超过段长度(防止越界访问,比如数组下标越界),然后用段号找到段的起始地址,加上偏移得到物理地址。

(三)分段的优点

  1. 符合程序逻辑结构:程序员可以直观地理解内存布局,比如调试时知道代码段在哪个区域,数据段在哪个区域。
  2. 支持段的共享与保护:多个程序可以共享同一个代码段(比如共享C语言标准库),每个段可以设置访问权限(代码段只读,数据段可读写)。

(四)分段的缺点

  1. 外部碎片问题回归:每个段需要连续的内存空间,段与段之间可能产生碎片(类似动态分区管理的问题)。
  2. 段大小不固定:大段可能难以分配,小段可能浪费空间(但比连续分区好,因为程序可以分成多个小段)。

五、段页式管理:集大成者

(一)设计思想:分段+分页,取长补短

  1. 先分段,再分页:每个段被划分为若干个页,结合分段的逻辑模块化和分页的内存高效利用。
    • 比如代码段分成3个页,数据段分成2个页,每个页装入页框,不需要连续。
  2. 地址结构:段号+段内页号+页内偏移。通过段表找到段对应的页目录表,再通过页表找到页框号,最后得到物理地址。

(二)地址转换过程(稍微复杂,但更灵活)

  1. 程序访问逻辑地址(段号S,段内逻辑地址A)。
  2. 通过段表找到该段的页目录表起始地址。
  3. 段内逻辑地址A分为页号P和页内偏移D。
  4. 通过页目录表和页表找到页框号F。
  5. 物理地址 = F×页大小 + D。

(三)优缺点

  • 优点
    • 既有分段的逻辑清晰(支持模块划分、共享、保护),又有分页的内存高效(消除外部碎片,内部碎片少)。
    • 适合大型程序和多任务系统(如Windows、Linux)。
  • 缺点
    • 地址转换需要多次访问内存(段表+页表),为了加速,通常使用"快表"(TLB,高速缓存)来缓存最近访问的段页信息。
    • 管理复杂度最高,需要维护段表和页表两级结构。

(四)实际应用

现代操作系统(如x86架构的Linux、Windows)普遍采用段页式管理,但为了简化,有时会让段的作用弱化(比如默认段号为0,只使用分页),但底层机制仍支持分段与分页的结合。


以上就是对本次关于操作系统博客内容的总结,后续我们将深入探讨操作系统更多知识。

我的个人主页,欢迎来阅读我的其他文章
https://blog.csdn.net/2402_83322742?spm=1011.2415.3001.5343
我的操作系统博客专栏
https://blog.csdn.net/2402_83322742/category_12916780.html?spm=1001.2014.3001.5482

非常感谢您的阅读,喜欢的话记得三连哦

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/86598.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/86598.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【编译原理】期末

单选题 (4分) 令文法G[E]为:E->ET | T T->T*F | F F-> (E) | i 句型 F*iT 的最左素短语是( ) A.F B.i C.T D.F*i B 短语: F*iT、F*i、F、i 素短语: i 最左素短语: i 单选题 (4分) 若在…

一个简单测试Deepseek吞吐量的脚本,国内环境可跑

一个简单测试Deepseek吞吐量的脚本,这里用DeepSeek-R1-Distill-Qwen-32B ,支持单卡4090 24G可跑,具体看你的硬件情况做调整,理论支持所有的模型,看你需要,可以修改模型名称,重点是pip使用国内的源,模型下载用阿里的ModelScope,无障碍下载,使用. 最后可以生成一个txt与html报表.…

前端基础知识JavaScript系列 - 19(正则表达式)

一、是什么 正则表达式是一种用来匹配字符串的强有力的武器 它的设计思想是用一种描述性的语言定义一个规则,凡是符合规则的字符串,我们就认为它“匹配”了,否则,该字符串就是不合法的 在 JavaScript中,正则表达式也…

Java锁机制知识点

一、锁的基础概念 1.1 什么是锁 在并发编程中,锁是用于控制多个线程对共享资源进行访问的机制。锁可以保证在同一时刻最多只有一个线程访问共享资源,从而保证数据的一致性。 1.2 锁的分类 可重入锁 vs 不可重入锁:可重入锁允许同一个线程…

2025下半年软考软件设计师(中级)怎么高效备考,目标是稳过线!

25下半年软考开始进入备考阶段,现在咱们就抛开那些文绉绉的官话,用大白话来聊聊2025下半年软考软件设计师(中级)怎么高效备考,目标是稳过线! 核心思想:抓大放小,真题为王&#xff0…

Jupyter常见操作(持续更新)

Jupyter常见操作(持续更新) 本文主要整理一些常见的或者比较简单的Jupyter操作,尽量保证一次性整理出来,方便需要但是忘记的情况下可以直接查,希望能当字典。 1.查看Jupyter内核 jupyter kernelspec list 2.使用指定…

连点成画面积计算算法

连点成画面积计算算法 问题分析与算法设计 1. 问题特征分析 闭合多边形(起点和终点相同)线段可能交叉形成复杂形状需要处理自交多边形可能有多个内部空洞点数较多(≥50个点),需要高效算法2. 解决方案选择 采用平面扫描算法结合多边形布尔运算来准确计算最外层边界包围的…

华为云Flexus+DeepSeek征文 | 华为云MaaS平台上的智能客服Agent开发:多渠道融合应用案例

华为云FlexusDeepSeek征文 | 华为云MaaS平台上的智能客服Agent开发:多渠道融合应用案例 🌟 嗨,我是IRpickstars! 🌌 总有一行代码,能点亮万千星辰。 🔍 在技术的宇宙中,我愿做永不…

03.BUG

Bug 1.软件测试的生命周期2. BUG2.1 表述BUG的要素2.2 BUG级别2.3 BUG的声命周期 1.软件测试的生命周期 ​ 软件测试贯穿于软件的整个生命周期:软件测试的生命周期(Software Testing Life Cycle, STLC),是指测试流程,这个流程是按…

【数据标注师】问答标注

目录 一、 **问答标注的认知底层架构**1. **三维评估体系**2. **四类问题处理范式** 二、 **五阶能力培养体系**▶ **阶段1:问题解析能力筑基(2周)**▶ **阶段2:答案质量评估训练**▶ **阶段3:复杂场景处理**▶ **阶段…

使用DBeaver 连接mysql,使用存储过程插入5万条数据

使用DBeaver连接MySQL并创建存储过程生成5万条数据 连接MySQL数据库 打开DBeaver,点击"数据库"菜单选择"新建连接",选择MySQL驱动。填写主机、端口、数据库名称、用户名和密码等信息,测试连接成功后保存。 创建测试表…

某省赛题-windows内存取证

1.获取admin用户密码是多少? 这里我们使用hashdump之后用john爆破没有结果,然后使用lsadump出来了flag 2.获取ip和主机名是什么? 主机名: 看注册表 SAM:记录了所有的用户 SYSTEM:可以看主机名 SOFTWARE&a…

【软考高项论文】论信息系统项目的成本管理

摘要 在信息系统项目管理里,成本管理是极为关键的环节,直接影响项目的顺利开展与最终成败。本文结合项目管理实际情况,从项目成本基准的形成过程、项目S曲线的绘制以及成本控制的具体实施三个方面,详细阐述了对信息系统项目成本管…

AI人工智能技术应用于人社服务领域的创新研究报告

AI 人工智能技术应用于人社服务领域的创新研究报告 一、研究背景与市场概况 1.1 研究背景与政策环境 人工智能技术正深刻改变政府治理模式和公共服务方式。在国家全面推进数字化转型的战略背景下,人社部《数字人社建设行动实施方案》明确提出:到 2025 年,人社数字化底座…

javaEE-mybatis操作数据库

前言 在MySQL的学习阶段,我们知道了如何使用JDBC去操作,也正是因为学习了JDBC也知道其操作的繁琐,每次的CRUD操作都需要从数据库连接池中去获取数据库连接,然后再编写SQL语句,并绑定对应的参数,接着通过连…

移动端测试——如何解决iOS端无法打开弹窗式网页(Webkit)

目录 一、什么是webkit? 1. 核心定义 2. iOS 的特殊限制 3. 弹窗拦截的逻辑 二、为什么 iOS 必须用 WebKit? 1. 苹果的官方理由 2. 实际后果 3.然而…… 三、如何解决iOS端无法打开弹窗式网页? 1.用户 1.1 safari浏览器 1.2 夸克…

【github】从本地更新仓库里的文件笔记

1. 打开GitHub官网,并登录到您的账户。 2. 在页面右上角的搜索栏中,输入您要更新的仓库名称,并选择相应的仓库进入。 3. 在仓库页面中,找到并点击红色的“Code”按钮,然后复制仓库的HTTPS或者SSH链接。 4. 右键包含…

Excel基础:数据编辑

Excel是Windows下最常用的数据处理工具,本文详细介绍Excel的数据编辑功能,熟练掌握编辑技巧能可以极大提升工作效率,文章最后附加了一张总结思维导图,方便大家查找和记忆。 文章目录 一、数据输入1.1 覆盖输入1.2 追加输入1.3 任…

JavaScript中Object()的解析与应用

在JavaScript中,Object() 是一个基础构造函数,用于创建对象或转换值为对象类型。它既是语言的核心组成部分,也提供了一系列静态方法用于对象操作。以下是详细解析和应用示例: 一、Object() 的基本行为 作为构造函数(…

stream使用案例

1.1 查找所有的偶数并求和 public static void p1() { List<Integer> numbers Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); int sum numbers.stream() .filter(num -> num % 2 0) .mapToInt(Integer::intValue) .sum() ; System.err.printf…