读懂操作系统之快表(TLB)原理(七)
前言
前不久、我们详细分析了TLB基本原理,本节我们通过一个简单的示例再次叙述TLB的算法和原理,希望借此示例能加深我们对TLB(又称之为快表,深入理解计算机系统(第三版)又称之为翻译后备缓冲区)的理解。
使用分页作为支持虚拟内存的核心机制可能会导致高性能开销,通过将地址空间划分成固定大小的小单元(即页面),分页需要映射大量信息,由于该映射信息通常存储在物理内存中,因此在逻辑上分页需要针对程序生成的每个虚拟地址进行额外的内存查找,在每条指令获取或显式加载或存储之前进入内存获取翻译信息的速度会非常慢。因此,我们的问题演变为:如何对逻辑地址进行高速翻译?我们如何加快地址转换的速度从而避免在分页时需要额外的内存引用?硬件支持是必要的吗?哪些操作需要操作系统参与?
TLB(快表,翻译后备缓冲区)原理和练习
当我们想加快查找速度时,通常需要借助于操作系统通常来完成,那就是来自操作系统的老朋友:硬件。为了加快地址翻译速度,我们将添加一个称为翻译后备缓冲区(TLB),TLB是芯片的内存管理单元(MMU)的一部分,因此,TLB是虚拟地址到物理地址翻译的硬件缓存。在每次引用虚拟内存时,硬件首先检查TLB,以查看是否已保留了所需的翻译(PTE),否则,硬件将检查TLB。如此这样将执行快速翻译而不必每次都去查阅页表(包含所有翻译),因每次进行内存引用必将对对性能的巨大影响,所以从另外一个角度讲,实际上TLB使虚拟内存成为可能。逻辑地址并计算出VPN、如何查找TLB、TLB缺失后如何处理等等通过图解方式来进行详细叙述,这里我们通过伪代码方式来进一步讲解TLB整个大概原理过程若有错误之处,还请批评指正,存有疑惑之处,还请先看操作系统专辑中对此更容易理解的叙述
VPN = (VirtualAddress & VPN_MASK) >> SHIFT;
(Success, TlbEntry) = TLB_Lookup(VPN);
if (Success == true)
{
if (CanAccess(TlbEntry.ProtectBits) == true)
{
Offset = VirtualAddress & OFFSET_MASK;
PhysAddr = (TlbEntry.PFN << SHIFT) | Offset;
Register = AccessMemory(PhysAddr);
}
else
{
RaiseException(PROTECTION_FAULT);
}
}
else
{
PTEAddr = PTBR + (VPN * sizeof(PTE));
PTE = AccessMemory(PTEAddr);
if (PTE.Valid == False)
RaiseException(SEGMENTATION_FAULT);
else if (CanAccess(PTE.ProtectBits) == false)
RaiseException(PROTECTION_FAULT);
else
TLB_Insert(VPN, PTE.PFN, PTE.ProtectBits);
RetryInstruction();
}
从逻辑地址提取出VPN(第1行),调用TLB_Lookup方法查找TLB中是否存持有VPN的翻译(第2行),获取到TLB是否命中的标识(Success)和TLB条目。若TLB命中(第3行),获取TLB条目中的保护位并调用CanAccess方法判断是否可访问(第5行),若可访问,从逻辑地址中提取出偏移量(第7行)。通过TLB条目中的物理页帧号即PFN、页偏移量以及基于页起始位置偏移计算出物理地址(第8行),传递物理地址并调用访问主存方法AccessMemory,使得寄存器指向主存地址空间(第9行)若TLB缺失(第16行),通过VPN和页表基寄存器计算PTE地址(第18行),传递PTE地址调用访问主存方法AccessMemory,这里是访问主存页表从而获取PTE,很显然,访问主存页表将导致额外的内存引用,操作成本很高(第19行),若PTE有效位为无效(第20行),则引发错误(第21行),同理若不可访问则引发保护位错误,这个时候将交由操作系统来进行缺页处理进行页面置换。否则调用TLB_Insert方法,将VPN和PTE中的PFN和保护位插入到TLB条目(第25行),一旦更新了TLB条目,那么硬件将重试缺页指令,如此将加速翻译,快速处理内存引用(第26行)
为了更清楚说明TLB的作用,我们通过一个简单的示例来跟踪虚拟地址翻译,最后看看TLB如何改善其性能。在此示例中,假设内存中有10个4字节整数的数组,从虚拟地址100开始。进一步假设我们有一个小的8位虚拟地址空间,具有16字节页面;因此,虚拟地址分为4位VPN(有16个虚拟页面)和4位偏移(即每页面有16个字节)。如下求数组元素之和
int sum = ; var array = new[] { , , , , , , , , , }; for (int i = ; i < ; i++)
{
sum += array[i];
}
上述数组中的10个元素在页表中的存放大概如下图所示,第1个元素位于(VPN = 6,偏移量 = 4),所以在第6页只能容纳3个4个字节整数元素,紧接着其他元素则分别放在第7和第8页。
为了简单起见,我们假设循环生成的唯一内存访问就是对数组的访问,忽略变量i和sum以及指令本身。当访问第一个数组元素(a[0])时,CPU将加载100的虚拟地址,硬件从地址中提取VPN(VPN = 06),并使用该地址检查TLB的有效转换,假设这是程序第一次访问数组,则结果将是引起TLB缺失。下一步开始访问元素a[1],好消息是:TLB命中,因为数组的第二个元素紧挨着第一个元素,所以它位于同一页上,因为在访问数组的第1个元素时已经访问了此页面,所以翻译已经加载到了TLB中。当访问元素a[3]时,此时又会引起页缺失,但接下来的a[4]..a[6]都将命中,因为它们和a[3]都在内存中同一页上。我们总结一下对数组的10次访问期间的TLB活动:未命中,命中,命中,未命中,命中,命中,命中,未命中,命中,命中。因此,我们的TLB命中率(即命中数除以访问总数)为70%
虽然这不是太高(实际上,我们希望命中率接近100%),但它不是零,这可能令人惊讶。即使这是程序第1次访问该数组时,由于空间局部性,TLB还是会提高性能。数组的元素紧密地包装在页面中(即它们在空间上彼此靠近),因此只有第1次访问页面上的元素才会产生TLB未命中。其实这也我们联想到了为何要进行缓存预热,因为第1次访问会导致缓存强制缺失。如果页面大小只是原来的2倍(32字节,而非16字节),则数组访问将遭受更少的丢失。由于典型的页面大小是4KB,因此这些类型的密集,基于数组的访问可凸显出出色的TLB性能,每页访问仅遇到一次未命中。
关于TLB性能的最后一点:如果程序在此循环完成后不久再次访问了数组,则假设我们有足够大的TLB来缓存所需的翻译,那么我们可能会看到更好的结果:命中,命中,命中,命中,命中,命中,命中,命中,命中,命中。在这种情况下,由于时间局部性即时间上的快速重新引用,TLB命中率会很高,像任何高速缓存一样,TLB依赖于时间和空间局部性而获得成功,程序具备这两个属性,往往大多时候,此二者不可同时兼得。
总结
相信之前和通过本节专述TLB原理,同时结合一个简单的示例详细的讲解,能够让大家更加明白TLB的实际作用,下一节我们进入关于操作系统内存管理最后一小节内容作为总结,然后我们开始进入程序执行、线程、进程等内容,感谢您的阅读,我们下节见。
读懂操作系统之快表(TLB)原理(七)的更多相关文章
- 读懂操作系统之缓存原理(cache)(三)
前言 本节内容计划是讲解TLB与高速缓存的关系,但是在涉及高速缓的前提是我们必须要了解操作系统缓存原理,所以提前先详细了解下缓存原理,我们依然是采取循序渐进的方式来解答缓存原理,若有叙述不当之处,还请 ...
- 读懂操作系统之虚拟内存TLB与缓存(cache)关系篇(四)
前言 前面我们讲到通过TLB缓存页表加快地址翻译,通过上一节缓存原理的讲解为本节做铺垫引入TLB和缓存的关系,同时我们来完整梳理下从CPU产生虚拟地址最终映射为物理地址获取数据的整个过程是怎样的,若有 ...
- 【Java基本功】一文读懂String及其包装类的实现原理
String作为Java中最常用的引用类型,相对来说基本上都比较熟悉,无论在平时的编码过程中还是在笔试面试中,String都很受到青睐,然而,在使用String过程中,又有较多需要注意的细节之处. S ...
- 读懂操作系统(x86)之堆栈帧(过程调用)
前言 为进行基础回炉,接下来一段时间我将持续更新汇编和操作系统相关知识,希望通过屏蔽底层细节能让大家明白每节所阐述内容.当我们写下如下C代码时背后究竟发生了什么呢? #include <stdi ...
- 读懂操作系统(x64)之堆栈帧(过程调用)
前言 上一节内容我们对在32位操作系统下堆栈帧进行了详细的分析,本节我们继续来看看在64位操作系统下对于过程调用在处理机制上是否会有所不同呢? 堆栈帧 我们给出如下示例代码方便对照汇编代码看,和上一节 ...
- 一篇文章读懂HTTPS及其背后的加密原理
HTTPS(全称: Hypertext Transfer Protocol Secure,超文本传输安全协议),是以安全为目标的HTTP通道,简单讲是HTTP的安全版.本文,就来深入介绍下其原理. 1 ...
- 一文读懂机器学习大杀器XGBoost原理
http://blog.itpub.net/31542119/viewspace-2199549/ XGBoost是boosting算法的其中一种.Boosting算法的思想是将许多弱分类器集成在一起 ...
- 《一篇文章读懂HTTPS及其背后的加密原理》阅读笔记
HTTPS(Hypertext Transfer Protocol Secure,超文本传输安全协议),是以安全为目标的HTTP通道,简单讲是HTTP的安全版.这篇文章深入介绍了它的原理. 当我们适用 ...
- 一文读懂 SuperEdge 边缘容器架构与原理
前言 superedge是腾讯推出的Kubernetes-native边缘计算管理框架.相比openyurt以及kubeedge,superedge除了具备Kubernetes零侵入以及边缘自治特性, ...
随机推荐
- 入门大数据---Spark_Structured API的基本使用
一.创建DataFrame和Dataset 1.1 创建DataFrame Spark 中所有功能的入口点是 SparkSession,可以使用 SparkSession.builder() 创建.创 ...
- 使用nginx配置域名及禁止直接通过IP访问网站
前段时间刚搭建好个人网站,一直没有关注一个问题,那就是IP地址也可以访问我的网站,今天就专门研究了一下nginx配置问题,争取把这个问题研究透彻. 1. nginx配置域名及禁止直接通过IP访问 先来 ...
- Python实用笔记 (15)函数式编程——装饰器
什么函数可以被称为闭包函数呢?主要是满足两点:函数内部定义的函数:引用了外部变量但非全局变量. python装饰器本质上就是一个函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外的功能,装饰 ...
- 编译ts时候src目录的ts分别生成了单独的js文件
{ "compilerOptions": { "target": "es5", "outDir": "bin- ...
- SpringBoot项目部署到tomcat
SpringBoot部署到tomcat 一.修改maven.xml 1.添加<.packaging>war</.packaging>,打包为war包 <packaging ...
- 每日一题 - 剑指 Offer 36. 二叉搜索树与双向链表
题目信息 时间: 2019-06-29 题目链接:Leetcode tag: 二叉搜索树 中序遍历 递归 深度优先搜索 难易程度:中等 题目描述: 输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的循 ...
- css3动画添加间隔
因项目需要,需要在元素上实现动画效果,并且需要有动画间隔.坑爹的是animation-delay只有在第一次动画开始的时候才起效. 在网上找了很多方法,最终的方法基本都是改动画规则,比如 @keyfr ...
- css文字不透明度怎么设置?
在css中有很多好看的样式都可以实现,css设置出来的样式让整个网页看起来也会非常美观,今天的这篇文章就给大家来介绍一下在css中怎么设置文字的透明度,让你的文字在网页中看起来是透明的. CSS设置透 ...
- Let's GO(二)
人生苦短,Let's GO Let's GO(一) Let's GO(二) Let's GO(三) Let's GO(四) 今天我学了什么? 1. Map map:映射,使用散列表(hash)实现 m ...
- ReadWriteLock锁的应用
对于 Lock 锁来说,如果要实现 "一写多读" 的并发状态(即允许同时读,不允许同时写),需要对 "写操作" 加锁,对 "读操作" 不作要 ...