Linux X86在下面TLB机制
TLB - translation lookaside buffer
快表。直译为翻译后备缓冲器,也能够理解为页表缓冲。地址变换快速缓存。
因为页表存放在主存中,因此程序每次訪存至少须要两次:一次訪存获取物理地址,第二次訪存才获得数据。
提高訪存性能的关键在于依靠页表的訪问局部性。
当一个转换的虚拟页号被使用时,它可能在不久的将来再次被使用到,。
TLB是一种快速缓存,内存管理硬件使用它来改善虚拟地址到物理地址的转换速度。
当前全部的个人桌面,笔记本和server处理器都使用TLB来进行虚拟地址到物理地址的映射。使用TLB内核能够快速的找到虚拟地址指向物理地址,而不须要请求RAM内存获取虚拟地址到物理地址的映射关系。这与data cache和instruction caches有非常大的相似之处。
TLB原理
当cpu要訪问一个虚拟地址/线性地址时,CPU会首先依据虚拟地址的高20位(20是x86特定的。不同架构有不同的值)在TLB中查找。假设是表中没有对应的表项。称为TLB miss,须要通过訪问慢速RAM中的页表计算出对应的物理地址。同一时候,物理地址被存放在一个TLB表项中,以后对同一线性地址的訪问,直接从TLB表项中获取物理地址就可以,称为TLB hit。
想像一下x86_32架构下没有TLB的存在时的情况,对线性地址的訪问,首先从PGD中获取PTE(第一次内存訪问)。在PTE中获取页框地址(第二次内存訪问)。最后訪问物理地址,总共须要3次RAM的訪问。假设有TLB存在,而且TLB hit。那么仅仅须要一次RAM訪问就可以。
TLB表项
TLB内部存放的基本单位是页表条目,相应着RAM中存放的页表条目。页表条目的大小固定不变的,所以TLB容量越大,所能存放的页表条目越多。TLB hit的几率也越大。可是TLB容量毕竟是有限的,因此RAM页表和TLB页表条目无法做到一一相应。
因此CPU收到一个线性地址,那么必须高速做两个推断:
1 所需的也表示否已经缓存在TLB内部(TLB miss或者TLB hit)
2 所需的页表在TLB的哪个条目内
为了尽量降低CPU做出这些推断所需的时间,那么就必须在TLB页表条目和内存页表条目之间的相应方式做足功夫
全相连 - full associative
在这样的组织方式下。TLB cache中的表项和线性地址之间没有不论什么关系。也就是说,一个TLB表项能够和随意线性地址的页表项关联。这样的关联方式使得TLB表项空间的利用率最大。
可是延迟也可能相当的大,由于每次CPU请求,TLB硬件都把线性地址和TLB的表项逐一比較,直到TLB hit或者全部TLB表项比較完毕。特别是随着CPU缓存越来越大,须要比較大量的TLB表项,所以这样的组织方式仅仅适合小容量TLB
直接匹配
每个线性地址块都可通过模运算相应到唯一的TLB表项,这样仅仅需进行一次比較,减少了TLB内比較的延迟。可是这个方式产生冲突的几率很高。导致TLB miss的发生。减少了命中率。
比方。我们假定TLB cache共包括16个表项。CPU顺序訪问下面线性地址块:1, 17 , 1, 33。
当CPU訪问地址块1时,1 mod 16 = 1。TLB查看它的第一个页表项是否包括指定的线性地址块1,包括则命中,否则从RAM装入。然后CPU方位地址块17,17 mod 16 = 1,TLB发现它的第一个页表项相应的不是线性地址块17。TLB miss发生。TLB訪问RAM把地址块17的页表项装入TLB;CPU接下来訪问地址块1,此时又发生了miss,TLB仅仅好訪问RAM又一次装入地址块1相应的页表项。因此在某些特定訪问模式下。直接匹配的性能差到了极点
组相连 - set-associative
为了解决全相连内部比較效率低和直接匹配的冲突,引入了组相连。这样的方式把全部的TLB表项分成多个组,每一个线性地址块相应的不再是一个TLB表项。而是一个TLB表项组。CPU做地址转换时,首先计算线性地址块相应哪个TLB表项组,然后在这个TLB表项组顺序比对。依照组长度,我们能够称之为2路,4路。8路。
经过长期的project实践,发现8路组相连是一个性能分界点。8路组相连的命中率差点儿和全相连命中率差点儿一样,超过8路。组内对照延迟带来的缺点就超过命中率提高带来的优点了。
这三种方式各有优缺点,组相连是个折衷的选择。适合大部分应用环境。当然针对不同的领域,也能够採用其它的cache组织形式。
TLB表项更新
TLB表项更新能够有TLB硬件自己主动发起。也能够有软件主动更新
1. TLB miss发生后。CPU从RAM获取页表项,会自己主动更新TLB表项
2. TLB中的表项在某些情况下是无效的,比方进程切换。更改内核页表等。此时CPU硬件不知道哪些TLB表项是无效的,仅仅能由软件在这些场景下。刷新TLB。
在linux kernel软件层,提供了丰富的TLB表项刷新方法,可是不同的体系结构提供的硬件接口不同。比方x86_32仅提供了两种硬件接口来刷新TLB表项:
1. 向cr3寄存器写入值时,会导致处理器自己主动刷新非全局页的TLB表项
2. 在Pentium Pro以后,invlpg汇编指令用来无效指定线性地址的单个TLB表项无效。
TLB刷新机制
在MMU开启的情形下。线性地 址到物理地址的转换须要经过页表的查找。假设每次都这么做的话显然对系统性能有影响。因此出现了这么一个cache,用来将已经此前的查找结果保存在这个 TLB中。显然TLB由于容量的限制不可能将全部的线性地址到物理地址的转换全部容纳进去,当TLB中全部的entry都被放置满的时候。处理器会决定将
一个旧的entry替换掉。
TLB本质上就是一块cache。所以也存在cache一致性的问题。比方假设操作系统改动了页表中的某一项 的映射关系,假设该项的映射恰好保存在TLB中。那么就出现了一致性的问题。与x86下系统物理内存与处理器间的cache一致性不一样,TLB的一致性 须要系统软件出面解决,而不是硬件。x86为此提供了两种方式来解决TLB一致性的问题:
1. 更新CR3. 假设cr3寄存器被又一次载入。那么会导致整个TLB无效。OS能够通过比方: mov eax, cr3; move cr3, eax;这种指令来刷新整个TLB。还有,我们知道Linux下进程切换时,会又一次载入cr3寄存器。由于新老进程的页表项是不同样的。因此须要使 TLB无效防止出现不一致的情况。
2. x86提供了一条INVLPG指令。该指令是特权指令。操作系统能够通过该指令对TLB中的单独的某一entry进行更新。
关于这条指令的具体信息。能够 參考一下 intel 64 and IA32 Architecture Software Developer's Manual. Linux kernel中使用到该指令的样例有:
<arch/x86/mm/pgtable.c>
void set_pte_vaddr(unsigned long vaddr, pte_t pteval)
{
...
/*
* It's enough to flush this one mapping.
* (PGE mappings get flushed as well)
*/
__flush_tlb_one(vaddr);
}
set_pte_vaddr函数在内核中被用来直接操作页文件夹表项,里面涉及到x86线性地址映射物理地址的原理,函数在最后调用__flush_tlb_one来刷新TLB中相应的项:
<arch/x86/mm/pgtable_32.c>
static inline void __flush_tlb_one(unsigned long addr)
{
if (cpu_has_invlpg)
__flush_tlb_single(addr);
else
__flush_tlb();
}
从函数的实现能够看到。假设CPU支持INVLPG指令,那么就调用 __flush_tlb_single函数来刷新TLB中的项(详细哪一项由虚拟线性地址addr来指定)。__flush_tlb_single的实现是:
static inline void __native_flush_tlb_single(unsigned long addr)
{
asm volatile("invlpg (%0)" ::"r" (addr) : "memory");
}
上面是一个很直观的invlpg指令使用范例。在__flush_tlb_one函数中。我们还能够看到__flush_tlb的调用,后者被用来刷新整个TLB,事实上就是本文前面提到的用mov指令倒换一下重写cr3.
在分页机制打开的情形下。当CPU要訪问一个线性地址时,首先会查找TLB,假设该线性地址的转换已经存储在TLB宾果,因此,直接访问物理地址(的确TLB它存储在VPN和PPN制图),在这一点上,你并不需要检查页文件夹页表。
假定当前的线性地址映射尚未保存TLB在,然后是一TLB miss,在这一点上,你需要找到该网页文件夹和页表项。然后结果被映射到记录TLB在。
Linux X86在下面TLB机制的更多相关文章
- Linux内存管理3---分页机制
1.前言 本文所述关于内存管理的系列文章主要是对陈莉君老师所讲述的内存管理知识讲座的整理. 本讲座主要分三个主题展开对内存管理进行讲解:内存管理的硬件基础.虚拟地址空间的管理.物理地址空间的管理. 本 ...
- Linux的原子操作与同步机制
Linux的原子操作与同步机制 .进程1执行完“mov eax, [count]”后,寄存器eax内保存了count的值0.此时,进程2被调度执行,抢占了进程1的CPU的控制权.进程2执行“cou ...
- Linux x86_64 APIC中断路由机制分析
不同CPU体系间的中断控制器工作原理有较大差异,本文是<Linux mips64r2 PCI中断路由机制分析>的姊妹篇,主要分析Broadwell-DE X86_64 APIC中断路由原理 ...
- Linux内存寻址之分段机制及分页机制【转】
前言 本文涉及的硬件平台是X86,如果是其他平台的话,如ARM,是会使用到MMU,但是没有使用到分段机制: 最近在学习Linux内核,读到<深入理解Linux内核>的内存寻址一章.原本以为 ...
- Linux mips64r2 PCI中断路由机制分析
Linux mips64r2 PCI中断路由机制分析 本文主要分析mips64r2 PCI设备中断路由原理和irq号分配实现方法,并尝试回答如下问题: PCI设备驱动中断注册(request_irq) ...
- 转:Linux内部的时钟处理机制全面剖析
Linux内部的时钟处理机制全面剖析 在 Linux 操作系统中,很多活动都和时间有关,例如:进程调度和网络处理等等.所以说,了解 Linux 操作系统中的时钟处理机制有助于更好地了解 Linux 操 ...
- 【Linux下进程机制】从一道面试题谈linux下fork的运行机制
今天一位朋友去一个不错的外企面试linux开发职位,面试官出了一个如下的题目: 给出如下C程序,在linux下使用gcc编译: #include "stdio.h" #includ ...
- Linux设备驱动之semaphore机制【转】
转自:http://blog.csdn.net/xiao229404041/article/details/7031776 Linux设备驱动之semaphore机制在Linux系统中,信号号是一种重 ...
- linux新内核的时钟机制代码
http://blog.chinaunix.net/uid-22810130-id-384173.html 如果说cfs是linux的一个很有创意的机制的话,那么linux中另一个创意就是nohz,我 ...
随机推荐
- 【VBA研究】查找目录以下全部文件的名称
作者:iamlaosong 目录里面保存有面单扫描的图像文件,文件名称为邮件号码.如今想收集这些邮件号码,由于量非常大,不可能一个一个的截取,仅仅能通过程序实现.假定,当前工作表B列里放的是存放这些图 ...
- (二十一)unity4.6学习Ugui中文文档-------交互-Supported Events & Raycasters
大家好,我是孙广东. 转载请注明出处:http://write.blog.csdn.net/postedit/38922399 更全的内容请看我的游戏蛮牛地址:mod=guide&view=m ...
- HDU1789Doing Homework again(贪婪)
HDU1789Doing Homework again(贪心) 题目链接 题目大意:给你n们作业的最后期限和过了这个期限没做须要扣的分数.问如何安排能够使得扣分最少. 解题思路:贪心,将扣分多的作业排 ...
- 使用Spring的JAVA Mail支持简化邮件发送(转)
闲来无事,翻看<Spring in Action>,发现Spring集成了对JAVA Mail的支持,有点小激动的看了一遍,嗯,话说真的简单了很多. Spring的邮件发送的核心是Mail ...
- Java的byte数组
今天我们讨论一下Java的byte数组.byte数组就是字节数组,每一位存一个字节.看下面程序,猜猜输出多少? package com.wjy.bytes; import java.io.File; ...
- Unity3d之MiniJson与LitJson之间的较量
由于项目不得不用到json来解析服务器端传来的数据,于是不得不选择一种在unity3d上面可用的json.开始根据网上推荐LitJson,于是下载下来源码,导入项目: 经过测试可以用:但是移植到ipa ...
- android 防止多次点击,它会导致事件侦听响应于其他接口
这里有情况: A当点击跳转至B介面,点击B接口结束后,到A界面中 1.此时在B界面中,设置点击事件,点击后结束B v.setOnClickListener(new OnClickListener() ...
- Gradle 修改 Maven 仓库地址(转)
近来迁移了一些项目到Android Studio,采用Gradle构建确实比原来的Ant方便许多.但是编译时下载依赖的网速又着实令人蛋疼不已. 如果能切换到国内的Maven镜像仓库,如开源中国的Mav ...
- PHP 文件操作类(创建文件并写入) 生成日志
<?php /** * 文件操作(生成日志)支持多条插入 * (假设插入多条语句并换行 用','逗号分开) * */ class log { public $path = './info.txt ...
- leetcode第一刷_Convert Sorted List to Binary Search Tree
好,二叉搜索树粉末登场,有关他的问题有这么几个,给你一个n,如何求全部的n个节点的二叉搜索树个数?能不能把全部的这些二叉搜索树打印出来? 这道题倒不用考虑这么多,直接转即可了,我用的思想是分治,每次找 ...