• 自动秒收录
  • 软件:1973
  • 资讯:56611|
  • 收录网站:203853|

IT精英团

夯实基本功 深刻理解TLB原则

夯实基本功 深刻理解TLB原则

浏览次数:
评论次数:
编辑: 温瑜
信息来源: ITPUB
更新日期: 2022-06-13 21:21:14
摘要

今天分享一篇TLB的好文章,希望大家夯实基本功,让我们一起深入理解计算机系统。TLB是translationlookasidebuffer的简称。首先,我们知道MMU的作用是把虚拟地址转换成物理地

  • 正文开始
  • 相关阅读
  • 推荐作品

今天,我分享一篇TLB的好文章。希望你能巩固好自己的基本功,让我们对计算机系统有深入的了解。是翻译后备缓冲区的缩写。首先我们知道MMU的作用是把虚拟地址翻译成物理地址。

MMU工作原理

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

Linux分页机制

MMU就是根据页表基址寄存器从PGD页表中查找PTE,最终找到物理地址(存储在PTE页表中的物理地址)。这就像在地图上显示你的家在哪里。为了找到你的家庭住址,我先确定你是中国,再确定你是一个省,然后再去一个城市。最后,找家也是一样的道理。让我们一层一层往下。如你所见,这个过程非常复杂。

如果我第一时间发现你家的具体位置,我会记下你的名字和地址。下次查的时候,是不是只要告诉我你叫什么名字,我就直接告诉你地址,不用一级一级查?四级页表查找过程需要四次存储器访问。可以想象,延迟极大地影响了性能。下图显示了页面查找过程的一个示例。如果以后有机会详细展开,可以在这里了解一下。

page table walk

TLB的本质是什么

实际上,TLB是一个贮藏处。数据缓存地址(虚拟地址或物理地址)和数据。缓存TLB虚拟地址及其映射的物理地址。根据虚拟地址,TLB查找缓存。它别无选择,只能根据虚拟地址来查找。因此,TLB是一个虚拟缓存。

硬件TLB出现后,虚拟地址到物理地址的转换过程发生了变化。虚拟地址首先被发送到TLB,以确认它是否命中缓存。如果缓存命中,可以直接获取物理地址。否则,在第一级查找页表以获得物理地址。并将虚拟地址和物理地址的映射关系缓存在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,但是会导致性能损失。

如何尽可能的避免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_struct获得)共同存储在页表基地址寄存器中。当查找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。

Linux系统调用的来龙去脉(第1部分)
« 上一篇 2022-06-13
  • Linux系统调用的来龙去脉(第1部分)
    0阅读 0条评论 个赞
    《linux系统调用的来龙去脉》分为上下两篇,本文为上篇。1.前言开始正题前先讲两个生活小案例来引出系统调用的意义。案例一:图书馆安居不用架高堂,书中自有黄金屋。娶妻莫恨无良媒,书中自有颜如玉。图书馆……
  • Linux系统调用的来龙去脉(第2部分)
    0阅读 0条评论 个赞
    《linux系统调用的来龙去脉》分为上下两篇,本文为下篇。1.LINUX系统调用实现linux系统调用分为3个部分:调用请求,响应请求,功能实现。linux系统调用流程图如下:系统调用提供给应用程……
  • Java代码技巧将效率提高一千倍
    0阅读 0条评论 个赞
    前言代码优化,一个很重要的课题。可能有些人觉得没用,一些细小的地方有什么好修改的,改与不改对于代码的运行效率有什么影响呢?这个问题我是这么考虑的,就像大海里面的鲸鱼一样,它吃一条小虾米有用吗?没用,……
  • 谈谈MySQL的10大经典错误
    0阅读 0条评论 个赞
    今天就给大家列举MySQL数据库中,最经典的十大错误案例,并附有处理问题的解决思路和方法,希望能给刚入行,或数据库爱好者一些帮助,今后再遇到任何报错,我们都可以很淡定地去处理。学习任何一门技术的同……
  • 深入了解前端路由哈希和历史的区别
    0阅读 0条评论 个赞
    前言没了解这两种路由前,不管是vue还是react在项目创建时难免会进行路由之间选择,在hash和history难免会纠结一番,或者是直接稀里糊涂用了默认带#的hash路由,看完这篇分享,保准让你之后……
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表
  • Linux系统调用的来龙去脉(第2部分)
    0阅读 0条评论 个赞
    《linux系统调用的来龙去脉》分为上下两篇,本文为下篇。1.LINUX系统调用实现linux系统调用分为3个部分:调用请求,响应请求,功能实现。linux系统调用流程图如下:系统调用提供给应用程……
  • 高并发架构的设计方法:面对高并发如何对症下药?
    1阅读 0条评论 个赞
    前言我们知道,“高并发”是现在系统架构设计的核心关键词。一个架构师如果设计、开发的系统不支持高并发,那简直不好意思跟同行讨论。但事实上,在架构设计领域,高并发的历史非常短暂,这一架构特性是随着互联网,……
  • 如何在Linux中向scp命令传递密码
    1阅读 0条评论 个赞
    将文件和目录从一个系统拷贝到另一个系统是任何系统管理员的常见任务。scp,也称为安全拷贝(securecopy),是一种Linux命令行实用程序,用于将文件从一台服务器安全地拷贝或传输到另一台服……
  • Java代码技巧将效率提高一千倍
    0阅读 0条评论 个赞
    前言代码优化,一个很重要的课题。可能有些人觉得没用,一些细小的地方有什么好修改的,改与不改对于代码的运行效率有什么影响呢?这个问题我是这么考虑的,就像大海里面的鲸鱼一样,它吃一条小虾米有用吗?没用,……
  • MySQL减肥3种方法 还有谁不行?
    2阅读 0条评论 个赞
    在使用SQL提数的时候,常会遇到表内有重复值的时候,比如我们想得到uv(独立访客),就需要做去重。在MySQL中通常是使用distinct或groupby子句,但在支持窗口函数的sq……
  • 太好了 一些高性能使用Python的技巧!
    1阅读 0条评论 个赞
    1.易混淆操作本节对一些Python易混淆的操作进行对比。1.1有放回随机采样和无放回随机采样importrandomrandom.choices(seq,k=1)#长度为k的lis……
  • 重温SQL Server的行到列和列到列的变化 并采访常见问题
    1阅读 0条评论 个赞
    行转列,列转行是我们在开发过程中经常碰到的问题。行转列一般通过CASEWHEN语句来实现,也可以通过SQLSERVER的运算符PIVOT来实现。用传统的方法,比较好理解。层次清晰,而且比较习……
  • 码头工人常见问题处理技巧
    1阅读 0条评论 个赞
    本文列举Docker常见问题24个及解决方法:▍1.Docker迁移存储目录默认情况系统会将Docker容器存放在/var/lib/docker目录下[问题起因]今天通过监控系统,发现公……
  • SQL中的三种重复数据删除方法 还有谁不行?
    1阅读 0条评论 个赞
    SQL去重是数据分析工作中比较常见的一个场景,今天给大家具体介绍3种去重的方法。在使用SQL提数的时候,常会遇到表内有重复值的时候,比如我们想得到uv(独立访客),就需要做去重。在MySQL中……
  • 如何在Bash脚本中使用强大的Linux测试命令
    1阅读 0条评论 个赞
    Linuxtest命令是Shell内置命令,用来检测某个条件是否成立。test通常和if语句一起使用,并且大部分if语句都依赖test。可以将一个元素与另一个元素进行比较,但它更常……
  • 不知道如何优雅地停下来挂断在线服务怎么办?
    0阅读 0条评论 个赞
    公司项目是用consul进行注册的,在发布微服务的时候,总是会导致调用方出现一定几率的调用失败。一开始百思不得其解,后来咨询了资深的同事才知道:原来是服务下线的时候没有优雅停机,没有去consu……
  • Kubernetes抛弃Docker 不要慌!这里有一套实用的方法告诉你~
    1阅读 0条评论 个赞
    导读Kubernetes是一个可移植、可扩展的开源平台,用于管理容器化的工作负载和服务,可促进声明式配置和自动化。Kubernetes拥有一个庞大且快速增长的生态系统,其服务、支持和工具的使用范围……
  • 我用Java在几分钟内处理了30亿条数据.
    2阅读 0条评论 个赞
    来源:https://c1n.cn/GM8hb目录场景说明模拟数据场景分析读取数据处理数据遇到的问题场景说明现有一个10G文件的数据,里面包含了18-70之间的整数,分别表示18-70岁的……
  • 老生常谈:如何在MySQL中查找数据
    0阅读 0条评论 个赞
    页的组成部分数据库中表的数据被划分为若各个页(page),每个页中又存储了很多行记录,而我们往MySQL中插入的每行记录就放到页当中的行记录中,InnoDB的页分为以下几个部分InnoDB页InnoD……
  • 干货:10个聚类算法的完整Python操作实例
    1阅读 0条评论 个赞
    来源:海豚数据科学实验室本文约7000字,建议阅读14分钟本文将介绍一篇关于聚类的文章,10种聚类介绍和Python代码。聚类或聚类分析是无监督学习问题。它通常被用作数据分析技术,用于发现数据中的有趣……
  • 深度知识的六个维度:如何让人工智能真正理解世界?
    1阅读 0条评论 个赞
    智能的真正标志不是知识,而是想象力。作者|GadiSinger编译|王玥编辑|陈彩娴什么知识让我们变得聪明?我们用来理解世界、解释新体验和做出深思熟虑的选择的认知结构是什么?定义一个阐明……
  • 为什么NodeJS是构建微服务的最佳选择?
    8阅读 0条评论 个赞
    作者|RonFybish译者|Sambodhi策划|闫园园什么是微服务微服务是一种应用架构,它将每个应用功能都放在自己的服务中,与其他服务隔离。这些服务是松散耦合的,可独立部署。这种架构……
  • NodeJs高级开发和超全性能优化指南
    1阅读 0条评论 个赞
    原文链接:https://juejin.cn/post/7095354780079357966作者:九儿的小书屋相信对于前端同学而言,我们去开发一个自己的简单后端程序可以借助很多的nodeJs的框架……
  • 架构进化 本文终于说清楚了~
    1阅读 0条评论 个赞
    相信大家都听说过单体和我服务,那么,单体到微服务架构的数据是如何演进的呢?这是个有意思的话题。今天,我们一起来看看,希望大家都有收获和启发。京东白条的快速发展满足了当前人们日益增长的消费需求。在京东商……
  • 管理关系型数据库常用的统计语句
    1阅读 0条评论 个赞
    以下文章来源于公众号-悦专栏,作者马听这一节内容,整理一些管理MySQL会经常用到的统计语句,比如表的碎片率、非InnoDB的表、所有用户和所有业务库等。1查看所有业务库selectsche……
最近发布资讯
更多