当前位置:   article > 正文

初识虚拟地址空间

虚拟地址空间

物理地址和虚拟地址

物理寻址: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 }

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

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

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

  • 1
  • 2
  • 3
  • 4

惊奇地发现,地址都是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

多级页表

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

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

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

  • 如果一级页表是空的,其二级页表则不存在。
  • 只需要一级页表总是驻留在内存中,而其他级的页表只最经常使用的才有必要缓存在内存中,这样能够有效地缓解内存的“压力”。
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Cpp五条/article/detail/476464
推荐阅读
相关标签
  

闽ICP备14008679号