初识虚拟地址空间

article/2025/9/30 10:36:12

物理地址和虚拟地址

物理寻址:CPU访问存储器的最原始方法就是直接用物理地址(Physical Address, 可简称PA)。物理地址是唯一的。
在这里插入图片描述
虚拟寻址:CPU通过生成一个虚拟的地址来访问内存,在访问前会把虚拟地址转化为物理地址。虚拟地址(virtual Address, 可简称VA)。
在这里插入图片描述
MMU:它是memory manage unit的缩写,内存管理单元。内存管理单元是CPU芯片上的硬件,它的作用是利用存放在内存中的表将虚拟地址转变成物理地址,这个转变的步骤被称为地址翻译

我们平常写程序所看到的地址都是虚拟地址。
验证:

//mycode.c 
1 # include <stdio.h>
2 # include <unistd.h>
3 int main(void)
4 {
5   int id;
6   int val = 1314;
7   id = fork();
8   while(1)
9   {
10     if(id == 0)
11     {
12       //child
13       printf("i am child, val=%d, my val_address: %p.\n",val , &val);       
14       sleep(1);
15     }
16     else{
17       //father
18       val = 520; //将val的值修改成520
19       printf("i am father, val=%d, my val_address: %p.\n",val, &val);
20       sleep(1);
21     }
22     sleep(1);
23   }
24   return 0;
25 }

运行以上程序。
在这里插入图片描述

//提取内容
i am father, val=520, my val_address: 0x7ffdca7cf3d8.
i am child, val=1314, my val_address: 0x7ffdca7cf3d8.

惊奇地发现,地址都是0x7ffdca7cf3d8,而地址中的内容一个是520,一个是1314,如果是同一个物理地址,值为什么会不一样!这说明我们看到的是虚拟地址,这些虚拟地址映射到了不同的物理地址。
在这里插入图片描述

我在文章里说的“内存”是物理内存

地址空间

地址空间:非负整数地址的有序集合。如果地址空间中的地址是连续的,则它是一个线性地址空间

地址空间有:虚拟地址空间物理地址空间。虚拟地址空间实际上是把外部存储器的磁盘中的部分当作了内存,所以也叫虚拟内存,因为它不是真正的内存。

地址空间大小的描述:地址空间内包含有2^n个地址,则称为n位地址空间。

接下来的讨论将假设为线性的地址空间。
在这里插入图片描述

这样就像把地址空间划分成了一块一块的样子。

  • 虚拟地址空间划分成了许多固定大小的块,这些块被称为虚拟页(页面)。
  • 物理地址空间划分成了许多固定大小的块,这些块称为物理页(页帧、页框)。

虚拟页的大小和物理页的大小讲究对齐原则。

虚拟页面有以下几种状况。
在这里插入图片描述

  • 未分配的:可理解为这块页还没有被使用,没有任何的数据和这个页关联,所以未分配的页不占据磁盘空间。
  • 已映射(已缓存):已经被缓存在了物理地址空间,也可以说当前映射在了物理页。
  • 未映射(未缓存):已经分配,但是还没有缓存在物理页(还没有映射到物理页)。

缓存似乎有点抽象,映射要好理解得多!

页表

页表:是一个页表条目(PTE,Page Table Entry的缩写)的数组,存放在物理存储器中。内存管理单元通过页表将虚拟页映射到物理页,将虚拟地址翻译成物理地址。
在这里插入图片描述
虚拟页号当作数组下标,也就是虚拟页号当作索引,通过虚拟页号就可以找到对应的页表条目。
在这里插入图片描述

1】虚拟页0和3还未被分配。
2】虚拟页1、2、4、7已映射到物理内存。
3】虚拟页5、6已被分配,但是还没有映射到物理内存。

有效位用于判断该虚拟页是否被映射到了物理内存中。CPU如果访问已经分配,但是还没有被映射到物理内存的虚拟页,这种情况称为缺页。假设现在CPU要访问vp5中的数据,当MMU内存管理单元从物理存储器中读PTE 5,它的有效位显示这个虚拟页还没有被映射,就会触发缺页异常,缺页异常会调用缺页异常处理程序

  • 1】选择一个牺牲页
  • 2】将牺牲页拷贝回虚拟内存
  • 3】修改牺牲页对应的页表条目
  • 4】把缺页的虚拟页映射到物理内存中牺牲页的位置
  • 5】再次跟新对应的页表条目。
  • 6】缺页异常处理程序返回
  • 7】重新启动导致缺页的指令
  • 8】正常

这个过程暂时停止访问,转而去处理缺页,所以这叫缺页中断
在这里插入图片描述

在这里插入图片描述
缺页中断时,操作系统需要选择内存里的一个页面,牺牲掉它的位置,让给要调入的虚拟页面。

对于这个要牺牲掉的牺牲页,如果它在内存里的时候被修改过了,就需要把它写回磁盘上,更新这个页面在磁盘上的副本。如果没有修改过,就不需要写回去。你用word写过一些东西吧,当你在写的时候,这个数据就被加载进了内存里,如果你忘记保存了,那么下一次可能数据就丢失了,这就是因为页面被你修改了,但是你还没有更新磁盘上的副本,那么是不能永久保存的。

那么操作系统会选择牺牲掉哪一个页面呢?
发生缺页中断的时候,操作系统也许会随机的选择一个牺牲页来置换,但是这样并不好!在虚拟内存和内存之间传送页,这个动作称为页面调度,或者页面置换 ,还可以称为交换。针对不同的优化方向,衍生出了许多地页面调度的策略,这能够尽可能地达到最优性能。

页面调度的策略就是页面调度算法,常见的页面调度算法:

--
最优页面调度最近未使用页面调度(NRU算法)
先进先出页面调度(FIFO算法)第二次机会页面调度
时钟页面调度最近最少使用页面调度(LRU算法)
工作集页面调度工作集时钟页面调度
最近不经常使用页面调度(NFU算法)……

虚拟内存保护了物理内存

上面所述的页表是简化的版本,实际上,页表条目(PTE)中不只有有效位,还有许多其他的标志位。

  • 修改位
  • 保护位
  • 访问位
  • 禁止高速缓存位
  • sup位

保护位:PTE增加了保护位起到了保护的作用,保护位实际上就是做了一些权限,限制这个PTE对应的页面是否可以读、写、执行。不然你以为被const修饰的内容为什么能做到只读的呢?这里只是简单地举个例子。

修改位:用于判断这个PTE所对应的页面是否被修改过,缺页中断要进行页面换出时,这是非常有用的,如果牺牲页面驻留在内存时被修改过了,那么就必须把该页面写回磁盘,目的是更新磁盘上该页面的副本。修改位也称为“脏位”,这个页面被修改了——>“这个页面脏了”

访问位:在发生缺页中断时,操作系统可以借助访问位的值来选择牺牲页。

高速缓存禁止位:顾名思义,这个标志位可以禁止该PTE对应的页面进行高速缓存。

sup位:这个位用于表示是否需要在内核模式(内核态)才能访问页面。

地址翻译

MMU是如何利用页表实现地址翻译的?

CPU中有一个寄存器,页表基址寄存器(PTBR),这个寄存器指向当前页表的首地址。而虚拟地址显示了虚拟页号(VPN)和虚拟页偏移量(VPO)。MMU通过虚拟页号找到对应的页表条目(PTE),因为虚拟页和物理页讲究对齐原则,所以虚拟页的偏移量和该物理页面的偏移量是一样的将页表条目(PTE)里的物理页号和物理页的偏移量串联起来,得到对应的物理地址。

在这里插入图片描述

加速地址翻译

上面所描述的页表实际上是慢表

什么?慢表?难不成还有快表吗!没错,页表有慢表和快表

之所以说前面描述的存储在物理内存中的页表是慢表,是因为有了分页机制后,当CPU产生一个虚拟地址时,内存管理单元MMU就需要去内存访问一次PTE,后面还要访问物理内存中的物理页面,至少要访问两次物理内存!导致现在至少访问两次物理内存才相当于原本的访问一次物理内存,那么还会有人需要分页机制吗?

实际上很多的程序总是反复地读取少量的页面,其他的页面很少被访问,根据这个突破点,在内存管理单元MMU中设置了一个硬件设备——>翻译后备缓冲器(Translation Lookaside Buffer,简称TLB)。 也可以称为快表或者相联存储器

快表实际上就是一个比较小的缓存,每个缓存行里保存着一个PTE

多级页表

当虚拟地址空间非常大的时候,对应的页表也就非常地大,比物理内存还要大,这是万万不行的!所以要想办法 压缩页表

压缩页表的最常用的办法就是划分层次结构,划分出层次结构,那么就衍生出了多级页表

好比以前没有网络的时候,学校要面对全校师生个人召开重要的会议,找学校里的一个人,但是学校的人太多了,常用的方法就是划分出层次来分批召开会议,领导先给各班的老师开会传达内容,然后各班老师来给寝室长开会传达内容,寝室长给其他人员开会传达内容,最终就可以找到这个人。
在这里插入图片描述
多级页表类似于这样的机制。
多级页表可以避免把全部的页表一直驻留在物理内存中,特别是一些不用的页表,免得浪费物理内存。

  • 如果一级页表是空的,其二级页表则不存在。
  • 只需要一级页表总是驻留在内存中,而其他级的页表只最经常使用的才有必要缓存在内存中,这样能够有效地缓解内存的“压力”。

http://chatgpt.dhexx.cn/article/xEm405cM.shtml

相关文章

虚拟地址空间,虚拟文件系统

1、虚拟地址空间 1、概念与原因 虚拟地址空间是一个抽象的概念&#xff0c;在IBM中&#xff0c;这样说道&#xff1a;它存在&#xff0c;但你看不见&#xff0c;就是虚拟的。虚拟地址空间就是这样一个东西。&#xff08;注意区分虚拟内存与虚拟地址空间&#xff09; 虚拟地址空…

彻底搞懂虚拟内存,虚拟地址,虚拟地址空间

程序经过编译后&#xff0c;变成了可执行的文件&#xff0c;可执行文件主要包括代码和数据两部分&#xff0c;代码是只读的&#xff0c;数据则是可读可写的。 可执行文件由操作系统加载到内存中&#xff0c;交由CPU去执行&#xff0c;现在问题来了&#xff0c;CPU怎么去访问代…

使用POI导出Excel(并使用公式)

使用POI导出Excel&#xff08;并使用公式&#xff09; 使用java直接生成Excel并填充数据 可以参考POI官方文档&#xff0c;就是对Sheet&#xff0c;row&#xff0c;cell&#xff0c;Formula等操作&#xff0c; https://poi.apache.org/components/index.html 这种方式也可以生成…

poi导出excel日期格式问题

POI导出Excel的时候有时需要日期格式&#xff0c;在筛选时是这样的 private XSSFWorkbook wb null; String dateFormat "yyyy-MM-dd";//或者"yyyy/MM/dd"格式,"yyyy/M/d"这样的格式不会自动补0 public void setCell(int index,Date value,bool…

POI导出Excel详细教程

文章目录 前言一、引入jar包依赖二、创建自定义导出Excel样式类三、创建核心导出工具类四、创建导出对象实体Bean五、具体使用案例5.1.创建SQL脚本和初始化数据5.2.写一个查询所有学生信息接口5.3.查询学生基本信息返回数据格式5.4.导出Excel方法5.5.通过页面导出按钮导出Excel…

Java使用POI导出Excel文件

Java使用POI导出Excel文件 POI概述Apache POI 下载依赖引用关系图如下所示:直接下载Maven下载 POI实例总结 POI概述 HSSF 是 POI 项目的 Excel 97(-2007) 文件格式的纯 Java 实现。XSSF 是 POI 项目的 Excel 2007 OOXML (.xlsx) 文件格式的纯 Java 实现。 HSSF 和 XSSF 提供了读…

Java用POI导出Excel表格中的数据

poi操作Excel 主要通过HSSF,XSSF两种方式。 HSSF只能解析.xls格式的excel文件&#xff0c;XSSF支持.xls与.xlsx两种格式。 功能&#xff1a; 传递一个Excel文件&#xff0c;拿到里面所有的数据&#xff0c;返回一个集合。 Excel中的数据是什么类型&#xff0c;就返回什么类型的…

springboot+poi导出excel

在web开发中经常遇到将数据写入excel并导出的需求&#xff0c;下面整理springbootpoi实现导出excel的实例。 搭建springboot工程&#xff0c;引入依赖&#xff0c;细节不在赘述。 引入poi依赖 <dependency><groupId>org.apache.poi</groupId><artifactId…

POI实现导入导出excel

poi在日常的导入导出中是比较常用到的&#xff0c;最近也总结了下接触到的poi相关的导入导出的一些代码&#xff0c;有问题可以指出&#xff1a; package com.poi;import km.org.apache.poi.hssf.usermodel.*; import km.org.apache.poi.hssf.util.HSSFColor; import km.org.a…

java使用Poi导出excel表格

随时随地阅读更多技术实战干货&#xff0c;获取项目源码、学习资料&#xff0c;请关注源代码社区公众号(ydmsq666) 在之前的一篇文章java操作Excel实战干货中展示了使用poi库读取excel表格的的用法&#xff0c;今天演示另一个常用功能&#xff0c;将数据导出到excel中&#xff…

POI导出Excel文件中文乱码

使用POI组件生产Excel文件时中文乱码&#xff0c;总结后可能错误原因如下&#xff1a; 后台导出Excel文件格式混乱 POI组件可生成.xls和.xlsx两种格式的Excel文件&#xff0c;设置文件格式时应注意与导出的格式相匹配。如果文件格式设置出错&#xff0c;则会出现以下错误&…

Java使用poi导出Excel之格式设置

最近接到一个需求&#xff0c;客户不满意原本导出的csv文件&#xff0c;想要导出Excel文件。不就导出Excel文件嘛&#xff0c;小意思&#xff0c;于是乎信心满满从网上扒导出的代码&#xff0c;一顿CV大法&#xff0c;搞定&#xff01;代码如下: import lombok.extern.slf4j.S…

Java使用POI导出Excel

目录 一、前景二、概念2.1. 简介2.2.Excel版本和相关对象2.3.WorkBook2.4.POI依赖 三、POI - 写3.1.代码示例3.2. 性能对比3.3. 测试rowAccessWindowSize3.4. 导出Excel样式设置 四、POI - 读4.1.代码示例4.2.读取不同的数据类型4.3.读取公式 五、POI - 遇到的坑5.1.为什么模板…

Java实现八大排序算法

原文链接&#xff1a; 八大排序算法总结与java实现 - iTimeTraveler 概述 因为健忘&#xff0c;加上对各种排序算法理解不深刻&#xff0c;过段时间面对排序就蒙了。所以决定对我们常见的这几种排序算法进行统一总结&#xff0c;强行学习。首先罗列一下常见的十大排序算法&…

通过java实现八大排序的功能

八大排序(java实现) 常见的排序算法如下&#xff1a; 直接插入排序希尔排序简单选择排序堆排序冒泡排序快速排序归并排序基数排序 它们都属于内部排序&#xff0c;也就是只考虑数据量较小仅需要使用内存的排序算法&#xff0c;他们之间关系如下&#xff1a; 稳定与非稳定 …

c语言基数为3变为基数为10,必须知道的C语言八大排序算法(收藏)

概述 排序有内部排序和外部排序&#xff0c;内部排序是数据记录在内存中进行排序&#xff0c;而外部排序是因排序的数据很大&#xff0c;一次不能容纳全部的排序记录&#xff0c;在排序过程中需要访问外存。 我们这里说说八大排序就是内部排序。 当n较大&#xff0c;则应采用时…

数据结构( 排序)

排序 1、排序的基本概念2、插入排序①.直接插入排序②.折半插入排序③.希尔排序 3、交换排序①.冒泡排序②.快速排序 4、选择排序①.简单选择排序②.树形选择排序③.堆排序 5、归并排序6、基数排序7、总结8、例题与应用 1、排序的基本概念 排序是计算机内经常进行的一种操作&a…

十大经典排序算法python版本_【程序员面试必备】动画详解十大经典排序算法(C语言版)...

欢迎访问我的博客原文 排序算法是程序员必备的基础知识&#xff0c;弄明白它们的原理和实现很有必要。本文中将通过非常细节的动画展示出算法的原理&#xff0c;配合代码更容易理解。 概述 由于待排序的元素数量不同&#xff0c;使得排序过程中涉及的存储器不同&#xff0c;可将…

八大排序算法详解(Java语言实现)

概述 因为健忘&#xff0c;加上对各种排序算法理解不深刻&#xff0c;过段时间面对排序就蒙了。所以决定对我们常见的这几种排序算法进行统一总结&#xff0c;强行学习。首先罗列一下常见的十大排序算法&#xff1a; 直接插入排序希尔排序简单选择排序堆排序冒泡排序快速排序归…

九大排序算法-C语言实现及详解

概述 排序有内部排序和外部排序&#xff0c;内部排序是数据记录在内存中进行排序&#xff0c;而外部排序是因排序的数据很大&#xff0c;一次不能容纳全部的排序记录&#xff0c;在排序过程中需要访问外存。 我们这里说说八大排序就是内部排序。 当n较大&#xff0c;则应采用…