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,我 ...
随机推荐
- 使用mysql-mmm实现MySQL高可用集群
背景:之前实现的mysql同步复制功能(见笔者之前文章http://blog.csdn.net/kingofworld/article/details/39210937)仅仅是双机热备功能,还不能做到 ...
- mysql登录报错 ERROR 1045 (28000)
1.现象: [root@localhost ~]# mysql -u root -p Enter password: ERROR 1045 (28000): Access denied for us ...
- Java 模拟队列(一般队列、双端队列、优先级队列)
队列: 先进先出,处理类似排队的问题,先排的.先处理,后排的等前面的处理完了,再处理 对于插入和移除操作的时间复杂度都为O(1).从后面插入,从前面移除 双端队列: 即在队列两端都能够insert和r ...
- 智能生活 “视”不可挡——首届TCL杯HTML5智能电视开发大赛等你来挑战
http://www.csdn.net/article/2014-06-04/2820063-TCL-Smart-TV-Innovation-Competation
- linux kickstart 自动安装
最近很多业务系统都是linux lnmp平台安装,反复的安装让人觉得很苦恼,仔细钻研了下kickstart .这里环境是red hat linux 5.8 32位,系统盘中的软件包里包含有kickst ...
- poj1243(经典dp)
题目链接:http://poj.org/problem?id=1243 题意:让你猜一个物品的价格,猜低了或者猜高了都会提示你.G,L,表示你有G次机会猜一个数,如果猜错了,G会减少1次,如果你的错误 ...
- Phalcon之 表单(Forms)
Phalcon中提供了 Phalcon\Forms组件以方便开发人员创建和维护应用中的表单. 以下的样例中展示了主要的用法: <?php use Phalcon\Forms\Form, Phal ...
- 孙鑫HTML视频学习总结
1. HTML中元素和标签 元素是由单个或一对标签定义的包含范围.一个标签就是左右分别有一个小于号(<)和大于号(>)的字符串.开始标签是指以不以斜杠(/)开头的标签,其内是一串允许的 ...
- jersey client上传下载文件
jersey client上传文件demo File file = new File("/tmp/test.jpg"); System.out.println(file.exist ...
- Python的控制结构(转)
首先我的工作第一语言是c/c++(面向对象子集).选择学习python一方面是因为看很多人都说python开发效率高,所以想验证一下:另一方面,Eric S. Raymond在文章:如何成为一名黑客 ...