虚拟内存是现代操作系统中最伟大的发明之一。它为每个进程提供了一个一致的、私有的地址空间,让每个进程产生了一种自己在独享主存的错觉。

为了讲清楚MMU是如何一步一步完成地址翻译,取出数据的,本篇文章在前4节中讲解了虚拟内存中一些重要的概念,比如,虚拟内存的作用,页命中,缺页异常处理,为什么需要TLB等等。最后,通过两个地址翻译的例子,详细解释了MMU地址翻译的过程。

1. 什么是虚拟内存?

  • 虚拟内存能够创建一个连续的更大的空间给进程使用,出现的原因是由于主存的空间是有限

  • 当运行多个进程或者一个进程需要更大的空间进行存储运行,主存显然是不够的,这个时候就需要更大更便宜的磁盘进行保存一部分数据。

  • 对于进程来说,虚拟内存就是一张连续的内存空间,这个空间有些在主存中,有些在磁盘中。

2. 虚拟内存的作用

  • 虚拟内存将主存看成是一个存储在磁盘上的地址空间的高速缓存,在主存中只保存活动区域,并根据需要在磁盘和主存之间来回传送数据,通过这种方式,可以高效地使用主存

  • 虚拟内存为每个进程提供了一致的地址空间,简化了内存管理。

  • 虚拟内存保护了每个进程的地址空间不被其他进程破坏。

3. 虚拟内存与物理内存

3.1 CPU存取数据

我们先来看下,CPU是如何根据地址取得数据的。

CPU 在这里生成的物理地址为 4,把地址发送给内存,然后内存从该地址获取其中保存的字,最后将其发送回 CPU。

MMU(Memory Management Unit)叫做内存管理单元,主要用来管理虚拟内存与物理内存的映射,由硬件自动完成。

3.2 物理地址常用术语

这里需要比较烧脑地介绍几个名词,后面理解MMU地址翻译的时候会用到

  • 物理内存(physical memory),主存RAM,实际能使用的物理空间。
  • 物理页(physical page),把物理内存按照页表的大小进行划分。
  • 物理地址(physical address,PA), 物理内存划分了根据物理页划分为很多块,通过物理地址进行定位。
  • 物理页号(physical page number,PPN) ,定位缓存中的数据字。
  • 物理页号偏移 (physical page offset, PPO),定位缓存中的数据块。
  • 缓存标记(cache tag,CT),在高速缓存中作为行匹配。
  • 缓存索引(cache index,CI),在高速缓存中作为组索引。
  • 缓存偏移(cache offset,CO),在高速缓存中用作行内偏移来选择目的数据块。
  • 物理页号偏移PPO = 组索引CI + 行内偏移CO。
  • 物理页号PPN = 行匹配CT。
  • 物理地址 PA = 物理页号 + 物理页号偏移 = PPN * page size + ppo。

3.3 虚拟地址常用术语

  • 虚拟内存(virtual memory),每个程序独有,存放在磁盘上,由多个虚拟页(VP, virtual page)组成。
  • 虚拟内存的地址编码称虚拟地址空间(virtual address space VAS),跟物理内存一样,但虚拟内存是每个进程独有的,其大小是根据操作系统的指令集位有关,如32位,64位,32位,每个进程就有4G,64位有个百亿的GB。
  • 虚拟页(virtual page,VP ),把虚拟内存按照页表的大小进行划分。
  • 虚拟地址(virtual address),通俗说是计算机进程加载地址的指令,进程给的虚拟地址通过MMU进行获取地址计算物理地址空间,然后获取物理地址对应的数据传送到CPU上。
  • 虚拟页号(virtual page number ,VPN) ,用于定位页表的PTE。
  • 虚拟页号偏移(virtual page offset VPO) ,跟PPO值一样,定位物理内存的地址。
  • TLB索引(TLB index,TLBI),在页表中作为组索引。
  • TLBT标记(TLB tag,TLBT),在页表中作为行匹配。
  • 虚拟页号VPN = TLBT + TLBI。
  • 虚拟地址 VA = 虚拟页号 + 虚拟页号偏移 。

3.4 页表常用术语

  • 页表(page tables),虚拟地址与物理地址的对应表集合。进程虚拟地址转换成物理地址,程序需要用到数据放在物理主存或磁盘某个位置,页表是存储在主存中。

  • 页表条目(page table entry PTE),虚拟地址与物理地址具体对应记录。页表是由多个页表条目PTE组成的数组,PTE 由一个有效位 和 n位地址字段组成,如果设置了有效位,那么地址字段就标识DRAM中相应的物理页的起始位置。

3.5 页命中/缺页

  1. 处理器产生一个虚拟地址。
  2. MMU生成PTE地址,并从高速缓存/主存请求得到它。
  3. 高速缓存/主存向MMU返回PTE。
  4. MMU构造物理地址,并把它传送给高速缓存/主存。
  5. 高速缓存/主存返回所请求的数据字给处理器。

  1. 处理器产生一个虚拟地址。
  2. MMU生成PTE地址,并从高速缓存/主存请求得到它。
  3. 高速缓存/主存向MMU返回PTE。
  4. PTE中的有效位是零,所以MMU触发了一次异常,传递CPU中的控制到操作系统内核中的缺页异常处理程序。
  5. 缺页处理程序确定出物理内存中的牺牲页,如果这个页面已经被修改了,则把它换出到磁盘。
  6. 缺页处理程序页面调入新的页面,并更新内存中的PTE。
  7. 缺页处理程序返回到原来的进程,再次执行导致缺页的指令。CPU将引起缺页的虚拟地址重新发送给MMU。因为虚拟页面现在缓存在物理内存中,所以就会命中,主存就会将所请求字返回给处理器。

4. 为什么有了高速缓存,还需要TLB呢?

局部性原则保证了在任意时刻, 程序将往往在一个较小的活动页面集合上工作,这个集合叫做工作集或者常驻集。

换句话说, 局部性原则揭示了一个现象:在一段时间内,我们会反复调入或调出同一个或几个虚拟页页面。而且,每次CPU产生一个VA时, MMU就必须查阅PTE,以便将VA翻译为PA, 注意是每次,所以开销很大

解决方法: 为了消除这样的开销,在MMU中包括了一个关于PTE的小缓存,称为翻译后备缓冲器,TLB(Translation Lookaside Buffer)。

关键点: 所有的地址翻译步骤都是在芯片上的MMU中执行的, 因此执行速度非常快。

说了这么多,下面就是本文的重点,我们看两个例子,虚拟地址是如何转换为物理地址的。

5. MMU是如何完成地址翻译的?

5.1 准备工作

5.1.1 内存系统的基本条件

假设我们有一个简单内存系统,我们做出如下规定:

  • 虚拟地址(VA):14 位

  • 物理地址(PA): 12 位

  • 页面大小:64 字节

  • 虚拟页号(VPN):8位

  • 虚拟页面偏移量(VPO): 6 位(64 = 2^6)

  • 物理页号(PPN):6位

  • 物理页偏移量(PPO):6位

5.1.2 TLB

假设TLB 有 16 个条目,并且是 4 路组相连的。TLB 缓存的是页表条目,页表条目是虚拟页号的唯一标识。所以,我们只需要用虚拟页号去访问 TLB。

我们使用 VPN 的低两位(2^2=4)作为组索引。剩下的6位作为标记位。然后用不同的值来初始化 TLB。

左边的红色区域(第一个列)并不是 TLB 的条目,仅仅是为了方便区分是哪一组

我们只根据索引来查找组,每一个条目都有一个标记位。一个 TLB 条目如果有效,它就含有一个物理地址。

5.1.3 页表

现在,我们还需要页表。假设,图中是我们页表的前 16 个条目。每一个页表有一个物理页号和一个有效位

如果有效位有效,则表示那个虚拟页面对应的物理页面在内存中,并且 PPN 项给出了对应的物理页号。

5.2 产生虚拟地址

假设 CPU 执行了一条指令,它产生了一个有效地址 0x3d4。它把这个地址传递给了 MMU。

我们需要找出对应的物理地址,然后从缓存或内存中取出数据

在这个例子中,虚拟页面偏移(VPO)是0x24,虚拟页号(VPN)是 0xf,TLB 索引(TLBI)是虚拟页号的低两位是 0b11,也就是 0x3。TLB 标记位(TLBT)是 3。

MMU 做的第一件是就是查询 TLB,所以,我们先取出索引位,值为 3。

我们找到第 3 组,我们在第 3 组中找标记位为 3 的表项

遍历这 4 个条目,有一个标记位为 7 的项,但它不是我们想要的,它的有效位为 0。再往后找,找到一个标记位为 3 并且有效位为 1

所以,我们在 TLB 中找到了页表条目。页表条目返回这个值。MMU 返回的物理页号是 0x0D

5.3 构造物理地址

现在我们可以构造物理地址,PPO的值总是等于VPO的值,可以直接拷贝过来,为0x24。

PPN的值从 TLB 缓存的 PTE 中得到,为0x0d。合在一起构成了物理地址 0x354

下一步是使用这个物理地址去看高速缓存中有没有这个物理地址的缓存。

5.4 遍历高速缓存

把 0x354送入高速缓存,请求高速缓存返回对应物理地址上的值,在这个例子中,我们只需要返回一个字节。

高速缓存收到请求后,首先去检查高速缓存中是否有块缓存了该字节

高速缓存先取出物理地址的索引位是 0b00101,也就是 0x5。

接着去第 5 组找。找标记位为 0xd 的项,有一个匹配的标记位且有效位为 1。这就是我们要在高速缓存中找的项。

偏移量是 0,所以我们去请求第五组偏移量为 0 的字节,值为 0x36。

缓存命中,高速缓存把这个字节返回给 MMU, MMU 把它传递给处理器。最后处理器可能把这个字节存储在一个寄存器里。

以上就是一个完整的地址翻译的例子,在这个例子中,并没有出现缺页的情况。

下面我们看一个在缺页异常处理中,是如何完成地址翻译的。

5.5 缺页处理

好了,我们来看下一个例子。这次 CPU 发送给 MMU 的虚拟地址是 0x0020。

和之前的例子一样,我们可以得到VPN为0x00,VPO为0x01,TLBI为0,TLBT为0x00。

第一步是检查 TLB 看是否有页表条目的缓存

在 TLB 中,如果缓存存在,它应该在第一组,并且它的标记位应该为 0。所以,我们在第 0 组内找标记位为 0 的项。

第一项是 0x03,不匹配,第二项是 0x09,不匹配,第三项是 0x00,匹配,但是有效位为 0。所以,这次 TLB 缓存不命中

查找缓存失败了,我们只能去内存中去读取页表中对应的页表条目

查看页表,寻找虚拟页号为 0 的项。检查对应的页表条目,看虚拟页是否在内存中

虚拟页号为 0 的项的有效位为1,我们就可以得到一个物理页号为0x28。根据物理页号和物理页面偏移量就可以构造出物理地址。

现在 MMU 拥有了物理地址,就可以将其发送到高速缓存。并请求高速缓存返回对应的物理地址上的一个字节。

高速缓存得到了这个物理地址。它取出对应的索引位,在这个例子中是 0x8。

所以我们去高速缓存的第八组,然后寻找对应的标记位,在这个例子中是0x28。

第八组有一个条目,它的标记位是 24,这里是一次缓存不命中

所以,缓存就要向内存传递物理地址去得到所需要的字节。相关内容本篇就不再做具体讲解,可以参考下这篇文章。24张图7000字详解计算机中的高速缓存

6. 总结

虚拟存储器的工作原理是有一些复杂,本文描述的也并不全是最真实的计算机中的工作方式,比如,PTE由一个有效位和一个地址字段组成其实是为了便于理解而假设出来的。

但是这种方式成功的解决了直接使用物理内存会出现的问题。比如,虚拟内存中连续存储解决了物理内存碎片化,资源利用率过低的问题;每个进程只能访问自己独立的用户空间而内核空间是共用的解决了进程间的安全问题;缺页异常和选择牺牲页的算法提高了内存读写的效率等等。

我们应该对虚拟存储器的工作原理有深层次的理解,可以更好的帮助我们理解系统是如何工作的,也可以帮助我们避免在使用malloc这类的管理虚拟存储器的分配程序时遇到的一些错误。

本文参考 《深入理解计算机系统》

【硬核】MMU是如何完成地址翻译的的更多相关文章

  1. 程序员需要了解的硬核知识之CPU

    大家都是程序员,大家都是和计算机打交道的程序员,大家都是和计算机中软件硬件打交道的程序员,大家都是和CPU打交道的程序员,所以,不管你是玩儿硬件的还是做软件的,你的世界都少不了计算机最核心的 - CP ...

  2. KVM地址翻译流程及EPT页表的建立过程

    本博文为原创,遵循CC3.0协议,转载请注明出处:http://blog.csdn.net/lux_veritas/article/details/9284635 ------------------ ...

  3. 《CSAPP》地址翻译

    本节所使用的符号: 地址翻译 地址翻译是一个N元素的虚拟地址空间(VAS)中的元素和一个M元素的物理地址空间(PAS)中元素之间的映射. 映射实现: MMU利用页表来实现这种映射.CPU中的一个控制寄 ...

  4. 袋鼠云研发手记 | 数栈·开源:Github上400+Star的硬核分布式同步工具FlinkX

    作为一家创新驱动的科技公司,袋鼠云每年研发投入达数千万,公司80%员工都是技术人员,袋鼠云产品家族包括企业级一站式数据中台PaaS数栈.交互式数据可视化大屏开发平台Easy[V]等产品也在迅速迭代.在 ...

  5. 嵌入ARM硬核的FPGA

    目前,在FPGA上嵌入ARM硬核的包括Xilinx的zynq系列以及Intel 的CYCLONEV系列. Zynq出来有一定市场,但是这个市场不是传统FPGA的主流市场,而是为了和微处理抢一些控制领域 ...

  6. Colder框架硬核更新(Sharding+IOC)

    目录 引言 控制反转 读写分离分库分表 理论基础 设计目标 现状调研 设计思路 实现之过五关斩六将 动态对象 动态模型缓存 数据源移植 查询表达式树深度移植 数据合并算法 事务支持 实际使用 展望未来 ...

  7. 可编程逻辑(FPGA)与硬核处理器(HPS)之间互联的结构

    本周我想进一步探究可编程逻辑(FPGA)与硬核处理器(HPS)之间互联的结构.我发现了三种主要方式,它们是如何映射并处理通信的,哪些组件需要管控时序并且有访问权限. AXI Bridge 为了能够实现 ...

  8. 【硬核教程】只需1秒—你也可以有自己的API文档

    Nothing is true. Everything is permitted. 写在前面 先聊聊为什么想到了要用Vuepress来代替原来写在Confluence上的文档. 大意是有个需要其他部门 ...

  9. 硬核数据结构,让你从B树理解到B+树

    本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是周五分布式系统的第八篇文章,核心内容是B+树的原理. 今天的文章是上周B树的延伸,所以新关注的或者是有所遗忘的同学建议先从下方链接回顾 ...

随机推荐

  1. 【题解】ball 数论

    题目 题目描述: 众所周知的是Dr.Bai 穷困潦倒负债累累,最近还因邦邦的出现被班上的男孩子们几乎打入冷宫,所以Dr.Bai 决定去打工赚钱. Dr.Bai 决定做玩♂球的工作,工作内容如下. 老板 ...

  2. 如何优雅的实现Mysql 增删改查,看完你就会了

    接着上期说,上期没写一条sql就把数据查询出来了,那如果要保存或者更新数据怎么办呢?能不能自己写sql呢? 保存数据 @GetMapping("save")//保存数据 publi ...

  3. WebGPU性能测试分析

    大家好,本文对WebGPU进行性能测试和分析,目的是为了对比WebGL和WebGPU在"渲染"和"计算"两个维度的性能差异,具体表现为CPU性能和FPS性能两个 ...

  4. Vue3全家桶升级指南二ref、toRef、toRefs的区别

    ref是对原始数据的拷贝,当修改ref数据时,模板中的视图会发生改变,但是原始数据并不会改变. toRef是对原始数据的引用,修改toRef数据时,原始数据也会发生改变,但是视图并不会更新. 在vue ...

  5. 31、DNS介绍

    [root@centos6 ~]# dig @8.8.8.8 www.baidu.com +trace ; <<>> DiG 9.8.2rc1-RedHat-9.8.2-0.3 ...

  6. 面试系列——Mysql索引

    1.索引分类 Hash索引Hash 索引查询效率很高,时间复杂度O(1).Mysql Innodb引擎不支持hash索引的.Hash索引适合精确查找,不适合范围查找. 平衡二叉树时间复杂度为 O(n) ...

  7. MinIO关闭公开桶的列表展示(S3 browser)

    MinIO通过配置桶策略关闭列表展示,以下为操作教程. 下载:s3browser官网 安装完成S3 browser后,添加账号 修改桶policy,选择桶public右键 删除 s3:ListBuck ...

  8. 单选按钮(radio)的取值和点击事件

    笔记走一波:获取单选按钮(radio)的选中值,以及它的点击事件的实现 首先要引入Jquery <script type="text/javascript" src=&quo ...

  9. 记两道最近做的pwn题(ciscn_2019)

    这两题为什么要记录呢,一个是我发现网上很多教程没写清楚(也可能是我太菜了),二是细节点很多,不同的大佬方式不太一样,有很多细节需要注意 ciscn_2019_es_2 这题是栈迁移的题,先上exp 1 ...

  10. Java | 日期类型的绍介和操作

    Date类 Date类在java.util.Date,Date类表示特定的瞬间,精确到毫秒.(毫秒是千分之一秒)毫秒可以对时间和日期进行计算,可以把日期转换为毫秒进行计算,计算完毕,再把毫秒转换为日期 ...