深入理解缓存 TLB 原理

今天分享一篇TLB的好文章,希望大家夯实基本功,让我们一起深入理解计算机系统。

TLB 是 translation lookaside buffer 的简称。首先,我们知道 MMU 的作用是把虚拟地址转换成物理地址。

MMU工作原理

虚拟地址和物理地址的映射关系存储在页表中,而现在页表又是分级的。64 位系统一般都是 3~5 级。常见的配置是 4 级页表,就以 4 级页表为例说明。分别是 PGD、PUD、PMD、PTE 四级页表。在硬件上会有一个叫做页表基地址寄存器,它存储 PGD 页表的首地址。

Linux分页机制

MMU 就是根据页表基地址寄存器从 PGD 页表一路查到 PTE,最终找到物理地址(PTE页表中存储物理地址)。这就像在地图上显示你的家在哪一样,我为了找到你家的地址,先确定你是中国,再确定你是某个省,继续往下某个市,最后找到你家是一样的原理。一级一级找下去。这个过程你也看到了,非常繁琐。如果第一次查到你家的具体位置,我如果记下来你的姓名和你家的地址。下次查找时,是不是只需要跟我说你的姓名是什么,我就直接能够告诉你地址,而不需要一级一级查找。

四级页表查找过程需要四次内存访问。延时可想而知,非常影响性能。页表查找过程的示例如下图所示。以后有机会详细展开,这里了解下即可。

page table walk

TLB 的本质是什么

TLB 其实就是一块高速缓存。

数据 cache 缓存地址(虚拟地址或者物理地址)和数据。TLB 缓存虚拟地址和其映射的物理地址。TLB 根据虚拟地址查找 cache,它没得选,只能根据虚拟地址查找。

所以 TLB 是一个虚拟高速缓存。硬件存在 TLB 后,虚拟地址到物理地址的转换过程发生了变化。虚拟地址首先发往 TLB 确认是否命中 cache,如果 cache hit 直接可以得到物理地址。

否则,一级一级查找页表获取物理地址。并将虚拟地址和物理地址的映射关系缓存到 TLB 中。既然 TLB 是虚拟高速缓存(VIVT),是否存在别名和歧义问题呢?如果存在,软件和硬件是如何配合解决这些问题呢?

TLB 的特殊

虚拟地址映射物理地址的最小单位是 4KB。所以 TLB 其实不需要存储虚拟地址和物理地址的低 12 位(因为低 12 位是一样的,根本没必要存储)。

另外,我们如果命中 cache,肯定是一次性从 cache 中拿出整个数据。所以虚拟地址不需要 offset 域。index 域是否需要呢?这取决于cache的组织形式。

如果是全相连高速缓存。那么就不需要 index。如果使用多路组相连高速缓存,依然需要index。

下图就是一个四路组相连 TLB 的例子。现如今 64 位 CPU 寻址范围并没有扩大到 64 位。64 位地址空间很大,现如今还用不到那么大。

因此硬件为了设计简单或者解决成本,实际虚拟地址位数只使用了一部分。这里以 48 位地址总线为例说明。

TLB 的别名问题

我先来思考第一个问题,别名是否存在。我们知道 PIPT 的数据 cache 不存在别名问题。物理地址是唯一的,一个物理地址一定对应一个数据。但是不同的物理地址可能存储相同的数据。

也就是说,物理地址对应数据是一对一关系,反过来是多对一关系。由于 TLB 的特殊性,存储的是虚拟地址和物理地址的对应关系。

因此,对于单个进程来说,同一时间一个虚拟地址对应一个物理地址,一个物理地址可以被多个虚拟地址映射。

将 PIPT 数据 cache 类比 TLB,我们可以知道TLB 不存在别名问题。而 VIVT Cache 存在别名问题,原因是 VA 需要转换成PA,PA 里面才存储着数据。中间多经传一手,所以引入了些问题。

TLB的歧义问题

我们知道不同的进程之间看到的虚拟地址范围是一样的,所以多个进程下,不同进程的相同的虚拟地址可以映射不同的物理地址。这就会造成歧义问题。

例如,进程A将地址 0x2000 映射物理地址 0x4000。进程 B 将地址 0x2000 映射物理地址 0x5000。当进程 A 执行的时候将 0x2000 对应0x4000 的映射关系缓存到 TLB 中。当切换 B 进程的时候,B 进程访问 0x2000 的数据,会由于命中 TLB 从物理地址0x4000取数据。

这就造成了歧义。如何消除这种歧义,我们可以借鉴 VIVT 数据 cache 的处理方式,在进程切换时将整个 TLB 无效。切换后的进程都不会命中 TLB,但是会导致性能损失。

  资料直通车:Linux内核源码技术学习路线+视频教程内核源码

学习直通车:Linux内核源码内存调优文件系统进程管理设备驱动/网络协议栈

如何尽可能地避免 flush TLB

首先需要说明的是,这里的 flush 理解成使无效的意思。我们知道进程切换的时候,为了避免歧义,我们需要主动 flush 整个 TLB。如果我们能够区分不同的进程的 TLB 表项就可以避免 flush TLB。

我们知道 Linux 如何区分不同的进程,每个进程拥有一个独一无二的进程 ID。如果 TLB 在判断是否命中的时候,除了比较 tag 以外,再额外比较进程 ID 该多好呢!这样就可以区分不同进程的TLB表项。

进程 A 和 B 虽然虚拟地址一样,但是进程 ID 不一样,自然就不会发生进程 B 命中进程 A 的 TLB 表项。所以,TLB 添加一项 ASID(Address Space ID) 的匹配。

ASID 就类似进程 ID 一样,用来区分不同进程的 TLB 表项。这样在进程切换的时候就不需要 flush TLB。但是仍然需要软件管理和分配 ASID。

如何管理 ASID

ASID 和进程 ID 肯定是不一样的,别混淆二者。进程 ID 取值范围很大。但是ASID 一般是 8 或 16 bit。所以只能区分 256 或 65536 个进程。我们的例子就以 8 位ASID说明。

所以我们不可能将进程 ID 和 ASID 一一对应,我们必须为每个进程分配一个ASID,进程 ID 和每个进程的 ASID 一般是不相等的。

每创建一个新进程,就为之分配一个新的 ASID。当 ASID 分配完后,flush 所有 TLB,重新分配 ASID。

所以,如果想完全避免 flush TLB的话,理想情况下,运行的进程数目必须小于等于 256。然而事实并非如此,因此管理 ASID 上需要软硬结合。

Linux kernel 为了管理每个进程会有个 task_struct 结构体,我们可以把分配给当前进程的 ASID 存储在这里。页表基地址寄存器有空闲位也可以用来存储ASID。当进程切换时,可以将页表基地址和 ASID (可以从 task_struc t获得)共同存储在页表基地址寄存器中。

当查找 TLB 时,硬件可以对比 tag 以及 ASID 是否相等(对比页表基地址寄存器存储的 ASID 和 TLB 表项存储的 ASID)。如果都相等,代表 TLB hit。否则TLB miss。当 TLB miss 时,需要多级遍历页表,查找物理地址。然后缓存到TLB 中,同时缓存当前的 ASID。

多个进程共享

我们知道内核空间和用户空间是分开的,并且内核空间是所有进程共享。既然内核空间是共享的,进程 A 切换进程 B 的时候,如果进程 B 访问的地址位于内核空间,完全可以使用进程 A 缓存的 TLB。但是现在由于 ASID 不一样,导致 TLB miss。

我们针对内核空间这种全局共享的映射关系称之为 global 映射。针对每个进程的映射称之为 non-global 映射。

所以,我们在最后一级页表中引入一个 bit (non-global (nG) bit)代表是不是 global 映射。当虚拟地址映射物理地址关系缓存到 TLB 时,将 nG bit 也存储下来。

当判断是否命中 TLB 时,当比较 tag 相等时,再判断是不是 global 映射,如果是的话,直接判断 TLB hit,无需比较 ASID。当不是 global 映射时,最后比较 ASID 判断是否 TLB hit。

什么时候应该flush TLB

我们再来最后的总结,什么时候应该 flush TLB。

  • 当 ASID 分配完的时候,需要 flush 全部 TLB,ASID 的管理可以使用 bitmap 管理,flush TLB 后 clear 整个 bitmap。
  • 当我们建立页表映射的时候,就需要 flush 虚拟地址对应的 TLB 表项。第一印象可能是修改页表映射的时候才需要 flush TLB,但是实际情况是只要建立映射就需要 flush TLB。原因是,建立映射时你并不知道之前是否存在映射,例如,建立虚拟地址 A 到物理地址 B 的映射,我们并不知道之前是否存在虚拟地址 A 到物理地址 C 的映射情况,所以就统一在建立映射关系的时候 flush TLB。

原文作者:【 一起学嵌入式

 

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

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

相关文章

无人机电力巡检方案在电网安全与维护中的应用

目前,无人机技术已经在各行各业都有广泛的应用,其中之一就是在电力巡检中的应用。无人机电力巡检方案以其高效、安全、精准的特点,为电网安全与维护带来了重大突破和进步。 一、无人机电力巡检方案是高效巡检的利器 传统的电力巡检方式需要人…

测试|Junit相关内容

测试|Junit相关内容 文章目录 测试|Junit相关内容0.Junit说明1.Junit注解TestDisabledBeforeAll和AfterAllBeforeEach和AfterEach 2.Junit参数化单参数多参数(多种/多组)CSV获取参数(支持多种)CSV文件获取参数(支持多种…

概率论与数理统计复习总结2

概率论与数理统计复习总结,仅供笔者复习使用,参考教材: 《概率论与数理统计》/ 荣腾中主编. — 第 2 版. 高等教育出版社《2024高途考研数学——概率基础精讲》王喆 概率论与数理统计实际上是两个互补的分支:概率论 在 已知随机…

linux(一)-----osi七层模型

1.七层模型的定义 1)物理层 (指的是网卡,网线等物理层面的硬件) 2)数据链路层 前两层可以概括为物理链路层,以二进制的数据形式在物理媒介上进行传输数据(传输协议ISO2100协议) …

LeetCode[1302]层数最深叶子节点的和

难度:Medium 题目: 给你一棵二叉树的根节点 root ,请你返回 层数最深的叶子节点的和 。 示例 1: 输入:root [1,2,3,4,5,null,6,7,null,null,null,null,8] 输出:15示例 2: 输入:r…

python爬虫 获取简单的get请求

打印结果: 原博主写的很厉害额,写的比较全面,大家可以去学习看看 参考原文: Python调用get或post请求外部接口_python调用post接口_纯洁的小魔鬼的博客-CSDN博客

【TypeScript】TS入门及基础学习(一)

【TypeScript】TS入门及基础学习(一) 【TypeScript】TS入门及基础学习(一)一、前言二、基本概念1.强类型语言和弱类型语言2.动态语言和静态语言 三、TypeScript与JavaScript的区别四、环境搭建及演练准备4.1 安装到本地4.2 在线运…

计算机视觉与图形学-神经渲染专题-第一个基于NeRF的自动驾驶仿真平台

如今,自动驾驶汽车可以在普通情况下平稳行驶,人们普遍认识到,真实的传感器模拟将在通过模拟解决剩余的极端情况方面发挥关键作用。为此,我们提出了一种基于神经辐射场(NeRF)的自动驾驶模拟器。与现有作品相…

【爬虫实践】使用Python从网站抓取数据

一、说明 本周我不得不为客户抓取一个网站。我意识到我做得如此自然和迅速,分享它会很有用,这样你也可以掌握这门艺术。【免责声明:本文展示了我的抓取做法,如果您有更多相关做法请在评论中分享】 二、计划策略 2.1 策划 确定您…

软件测试(功能、接口、性能、自动化)详解

一、软件测试功能测试 测试用例编写是软件测试的基本技能;也有很多人认为测试用例是软件测试的核心;软件测试中最重要的是设计和生成有效的测试用例;测试用例是测试工作的指导,是软件测试的必须遵守的准则。 黑盒测试常见测试用…

idea运行web老项目

idea打开老项目 首先你要用idea打开老项目,这里看我之前发的文章就可以啦 运行web项目 1. 编辑配置 2. 添加tomcat项目 3. 设置tomcat参数 选择本地tomcat,注意有的tomcat版本,不然运行不了设置-Dfile.encodingUTF-8 启动,这样…

vue3实现拖拽排序

效果&#xff1a; 实现 <template><div class"box"><divv-for"(item, index) in items":key"item.id"class"item":style"{ order: item.order }":draggable"true"dragstart"onDragStart(in…

【测试联调】如何在前后端测试联调时优雅的构造异常场景

目录 背景 使用iptables实现 利用iptables丢弃某ip数据包 使用 -L 列出所有规则 IP 连通性 通信 测试 插入一条规则&#xff0c;丢弃此ip 的所有协议请求 列出所有规则 测试 丢弃规则内的IP 连通性 清除 规则列表的 限制 模拟ip进行丢包50%的处理。 mysql proxy 代理…

脑电信号处理与特征提取——6.运用机器学习技术和脑电进行大脑解码(涂毅恒)

目录 六、运用机器学习技术和脑电进行大脑解码 6.1 前言 6.2 基于脑电数据的机器学习基础分析 6.3 基于脑电数据的机器学习进阶分析 6.4 代码解读 六、运用机器学习技术和脑电进行大脑解码 6.1 前言 6.2 基于脑电数据的机器学习基础分析 6.3 基于脑电数据的机器学习进阶分…

快速增加Shopee,lazada店铺销量的秘籍大揭秘

在竞争激烈的电商市场中&#xff0c;如何快速提高Shopee。lazada店铺的销量一直是卖家们关注的焦点。 优化产品信息&#xff1a;在Shopee平台上&#xff0c;完整填写产品标题、描述和关键词等信息非常重要。确保您的产品信息准确、清晰&#xff0c;并包含与目标买家搜索相关的…

C语言笔试题训练【第一天】

目录 第一题 第二题 第三题 第四题 第五题 大家好&#xff0c;我是纪宁。 从今天开始博主会日更一些经典的C语言笔试题&#xff0c;持续20天左右。题目类型为5道选择题加2道编程题&#xff0c;希望能和大家一起进步。 第一题 1.读程序&#xff0c;下面程序正确的输出是&…

如何在Visual Studio Code中用Mocha对TypeScript进行测试

目录 使用TypeScript编写测试用例 在Visual Studio Code中使用调试器在线调试代码 首先&#xff0c;本文不是一篇介绍有关TypeScript、JavaScript或其它编程语言数据结构和算法的文章。如果你正在准备一场面试&#xff0c;或者学习某一个课程&#xff0c;互联网上可以找到许多…

微信小程序wx.getlocation接口权限申请总结

先附上申请通过截图 插播内容&#xff1a;可代开通&#xff0c;保证通过。wx.getLocation接口&#xff08;获取当前的地址位置&#xff09; qq&#xff1a; 308205428 如何申请 当申请微信小程序的wx.getLocation接口权限时&#xff0c;你可以…

Go语言进阶语法八万字详解,通俗易懂

文章目录 File文件操作FileInfo接口权限打开模式File操作文件读取 I/O操作io包 文件复制io包下的Read()和Write()io包下的Copy()ioutil包总结 断点续传Seeker接口断点续传 bufio包bufio包原理Reader对象Writer对象 bufio包bufio.Readerbufio.Writer ioutil包ioutil包的方法示例…

gitlab CI/CD 安装 gitlab runner

一、为什么需要安装gitlab runner &#xff1f; 极狐GitLab Runner 极狐GitLab Runner 是在流水线中运行作业的应用&#xff0c;与极狐GitLab CI/CD 配合运作。 说白了就是你部署的一个agent。 二、如何安装&#xff1f; 1.介绍通过helm部署github runner 2.helm添加仓库 h…