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

操作系统-虚拟内存篇

虚拟内存

虚拟内存的设计目标是避免程序直接操作物理内存—— 若程序直接引用绝对物理地址,可能因地址冲突导致程序互相干扰,甚至引发系统崩溃。其实现核心是 “地址隔离与映射”:

虚拟内存的概念是由操作系统为每个程序分配一套虚拟地址,然后再由一个中间结构来记录虚拟地址到真实地址的映射关系

由此我们得出结论

  • 程序使用的内存地址为虚拟内存地址
  • 硬件使用的内存地址为物理内存地址

操作系统使用CPU芯片中的内存管理单元(MMU)实现虚拟地址和真实地址的映射

那么MMU是怎么实现这种映射关系的呢

是通过内存分段和内存分页来实现的

内存分段

内存分段的核心思路是:按程序的功能模块(如代码段、数据段、栈段)划分虚拟地址空间,每个模块对应一个 “段”,再通过段表实现虚拟段到物理段的映射

虚拟地址通过段表和物理地址做映射,通过段号作为索引快速找到段基地址和段界限等信息。段基地址就是当前段在物理内存中的起始位置,加上偏移量就是这个虚拟地址需要的全部真实物理地址空间。然而分段的方式会导致2个问题的出现

  1. 内存碎片
  2. 内存交换效率低

内存碎片的产生这里就不细讲了,参考JVM中的标记-清除算法大概心里就清楚了。

不过内存碎片分为外部内存碎片和内部内存碎片,对于分段来说,是按程序大小分配的段空间,一般不存在内部内存碎片,只会存在外部内存碎片,也就是段段之间的空间无法再分配导致浪费的情况。

为了解决内存碎片的问题,引入了内存交换方法

内存交换的本质如下,a和b两个段之间有100m空间碎片无法被利用,将b传入磁盘再重传内存中,重传的时候直接紧跟a后面实现,对于这个内存交换空间也成为Swap空间,是从磁盘划分出来用于磁盘和内存的空间交换。

从这里我们大概也能知道为什么交换效率低了,空间碎片不可避免且如果启动关闭程序变得频繁,内存碎片增多,交换次数上升,而交换是通过磁盘IO来操作的,一切就不言而喻了。于是出现了内存分页

内存分页

分页的本质是将虚拟内存和物理内存也按照固定大小进行连续划分,并且一一映射,减少了内存交换的数据数量。使用段的时候,每次交换都需要以段为单位,现在交换以页为单位

如果进程需要的虚拟内存无法找到对应物理内存,系统就会产生缺页异常来进入系统内核态,由内核分配物理空间并更新页表,恢复程序正常运行

内存分页机制下,分配内存的基本单位为页,因此可能会出现内部内存碎片的问题,不过也问题不大,页本身就很小,即使有大量这点碎片无足轻重。并且每个程序只能产生1个内部内存碎片,因此不可能出现碎片过多程序拖慢的问题

分页的映射实际上是和分段差不多的,不过做了优化,由于页很小,因此页数是很多的,如果做一一映射会导致大量内存用来存储页表

为了解决上诉问题,又引入了多级页表的概念,概念图如下

一级页表的痛点

以 32 位系统、4KB 页大小为例:

  • 虚拟地址空间总大小 = 4GB,每页 4KB,因此虚拟页数量 = 4GB / 4KB = 1,048,576 个(约 100 万);
  • 若采用 “一级页表”,每个页表项需 4 字节(存储物理页号等信息),则一级页表总大小 = 100 万 × 4 字节 = 4MB。

这会导致两个问题:

  1. 空间浪费:每个程序无论实际使用多少虚拟页,都需分配 4MB 页表空间
  2. 内存占用高:若系统同时运行 100 个程序,仅页表就需占用 400MB 物理内存,资源消耗过大。

多级页表的优化逻辑

多级页表的核心是 “按需创建下级页表”—— 将虚拟地址的 “页号” 拆分为多个层级,仅为已使用的虚拟页创建下级页表,未使用的层级无需分配空间。以 “二级页表” 为例:

  1. 虚拟地址拆分:将 32 位虚拟地址拆分为 “一级页号(10 位) + 二级页号(10 位) + 页内偏移量(12 位)”;
  2. 一级页表作用:仅存储 “一级页号 → 二级页表基地址” 的映射,每个一级页表项对应一个二级页表;
  3. 二级页表作用:存储 “二级页号 → 物理页号” 的映射,仅为已使用的虚拟页创建二级页表项。

(3)二级页表的空间优势

仍以 32 位系统、4KB 页大小为例:

  • 一级页表项数量 = 2^10 = 1024 个,总大小 = 1024 × 4 字节 = 4KB;
  • 每个二级页表项数量 = 2^10 = 1024 个,总大小 = 4KB;若程序仅使用 10 个虚拟页,则仅需创建 1 个二级页表(4KB),无需创建其他 1023 个二级页表;
  • 程序总页表空间 = 一级页表(4KB) + 1 个二级页表(4KB) = 8KB,远小于一级页表的 4MB,空间利用率大幅提升。

段页式内存管理

分段的优势是 “按功能模块隔离地址”,分页的优势是 “无外部碎片、交换效率高”。通过 “段页式内存管理”—— 先分段,再分页,实现完美结合

1. 段页式的核心逻辑

将虚拟地址空间先按 “段” 划分(如代码段、数据段),每个段再按 “页” 划分(固定大小的虚拟页),物理内存仅按 “页” 划分。映射过程分为三步:

  1. 段表查询:虚拟地址中的 “段号” 查询段表,获取该段的 “页表基地址”(每个段对应一个独立的页表);
  2. 页表查询:用虚拟地址中的 “页号” 查询该段对应的页表,获取 “物理页号”
  3. 计算物理地址:物理地址 = 物理页号 × 页大小 + 页内偏移量。

2. 段页式的优势与应用

  1. Windows、Linux、macOS 这些主流操作系统均采用段页式内存管理,平衡了地址隔离性、内存利用率与访问性能;
  2. 只有很少的内部内存碎片且提高了交换效率,并且有了分段的优势,程序之间的隔离性提高
http://www.dtcms.com/a/359085.html

相关文章:

  • 数据结构(顺序表力扣刷题)
  • 使用 Visio Viewer 查看 Visio 绘图文件
  • GEE中上传研究区域范围
  • 个性化导航新体验:cpolar让Dashy支持语音控制
  • 仓颉基于http调用DeepSeek
  • 【MySQL数据库】索引 - 结构 学习记录
  • Linux之Shell编程(三)流程控制
  • 知网文献高级检索方法
  • 防护墙技术(一):NAT
  • 如何调整Linux系统下单个文件的最大大小?
  • 2025年09月计算机二级Java选择题每日一练——第十二期
  • 介绍分布式事务之Seata
  • NV032NV037美光固态闪存NV043NV045
  • C++世界的大门——基础知识总结
  • 银河麒麟系统无法打开360浏览器的解决办法以及安装initramfs-tools报错解决方案
  • “HEU-AUTO”无线上网使用指南
  • 【开题答辩全过程】以 基于springboot的户外越野活动管理系统为例,包含答辩的问题和答案
  • 【CUDA进阶】MMA分析Bank Conflict与Swizzle(上)
  • Python 数据分析:计算,分组统计2,df.groupby()和grouped.agg()。听故事学知识点怎么这么容易?
  • 大模型推理显卡对比:Tesla P40 vs Titan RTX vs RTX A3000
  • GaussDB生产扩容引起的PANIC问题处理案例
  • 重叠IO模型
  • MySQL基础理解入门
  • 微服务架构中的 “双保险“:服务保护与分布式事务解决方案实战
  • 执行一条Select语句流程
  • Linux从入门到进阶--第四章--Linux使用操作
  • 深度学习核心损失函数详解:交叉熵、MSE、对比学习(InfoNCE)
  • Linux中的Shell编程 第一章
  • TechPowerUp GPU-Z中文版:专业显卡检测工具
  • 分分合合,门模块方案又兴起了