各位老铁,你们好!面试
上周大白有事停更1次,最近在想如何让你们在10分钟中有所收获,因而准备搞一个"什么是xxx"系列,写一些精悍的知识点。缓存
先抛一道阿里面试题给你们热热身,引出今天的主角-缺页异常Page Fault。服务器
谈谈对缺页异常Page Fault的理解。app
话很少说,集合上车。
ide
以32位的Linux系统为例,每一个进程独立拥有4GB的虚拟地址空间,根据局部性原理没有必要也不可能为每一个进程分配4GB的物理地址空间。函数
64位系统也是同样的道理,只不过空间寻址范围大了不少不少倍,进程的虚拟地址空间会分为几个部分:性能
实际上只有程序运行时用到了才去内存中寻找虚拟地址对应的页帧,找不到才可能进行分配,这就是内存的惰性(延时)分配机制。学习
对于一个运行中的进程来讲,不是全部的虚拟地址在物理内存中都有对应的页,如图展现了部分虚拟地址存在对应物理页的状况:优化
虚拟地址空间根据固定大小通常是4KB进行划分,物理内存能够设置不一样的页面大小,一般物理页大小和虚拟页大小是同样的,本文按照物理页4KB大小展开。ui
通过前面的分析,咱们将面临一个问题:如何将虚拟地址准确快速地映射到物理页呢?
>>>高能预警 敲黑板 本段小结<<<
1. Linux的虚拟地址空间就是空头支票,看着很大可是实际对应的物理空间只有不多的一部分。2.内存的惰性分配是个有效的机制,能够保证内存利用率和服务器利用率,是资源合理配置的方法。
3.大量的虚拟地址到物理地址的快速准确地查询转换是一个难题。
CPU并不直接和物理内存打交道,而是把地址转换的活外包给了MMU,MMU是一种硬件电路,其速度很快,主要工做是进行内存管理,地址转换只是它承接的业务之一。
一块儿看看MMU是如何搞定地址转换的。
每一个进程都会有本身的页表Page Table,页表存储了进程中虚拟地址到物理地址的映射关系,因此就至关于一张地图,MMU收到CPU的虚拟地址以后开始查询页表,肯定是否存在映射以及读写权限是否正常,如图:
对于4GB的虚拟地址且大小为4KB页,一级页表将有2^20个表项,页表占有连续内存而且存储空间大,多级页表能够有效下降页表的存储空间以及内存连续性要求,可是多级页表同时也带来了查询效率问题。
咱们以2级页表为例,MMU要先进行两次页表查询肯定物理地址,在确认了权限等问题后,MMU再将这个物理地址发送到总线,内存收到以后开始读取对应地址的数据并返回。
MMU在2级页表的状况下进行了2次检索和1次读写,那么当页表变为N级时,就变成了N次检索+1次读写。
可见,页表级数越多查询的步骤越多,对于CPU来讲等待时间越长,效率越低,这个问题还须要优化才行。
>> 本段小结 敲黑板 划重点 <<
1.页表存在于进程的内存之中,MMU收到虚拟地址以后查询Page Table来获取物理地址。2.单级页表对连续内存要求高,因而引入了多级页表,可是多级页表也是一把双刃剑,在减小连续存储要求且减小存储空间的同时下降了查询效率。
MMU和TLB的故事就这样开始了...
CPU以为MMU干活虽然卖力气,可是效率有点低,不太想继续外包给它了,这一会儿把MMU急坏了。
MMU因而找来了一些精通统计的朋友,通过一番研究以后发现CPU用的数据常常是一小搓,可是每次MMU都还要重复以前的步骤来检索,害,就知道埋头干活了,也得讲究方式方法呀!
找到瓶颈以后,MMU引入了新武器,江湖人称快表的TLB,别看TLB容量小,可是正式上岗以后干活还真是不含糊。
当CPU给MMU传新虚拟地址以后,MMU先去问TLB那边有没有,若是有就直接拿到物理地址发到总线给内存,齐活。
TLB容量比较小,不免发生Cache Miss,这时候MMU还有保底的老武器页表 Page Table,在页表中找到以后MMU除了把地址发到总线传给内存,还把这条映射关系给到TLB,让它记录一下刷新缓存。
TLB容量不满的时候就直接把新记录存储了,当满了的时候就开启了淘汰大法把旧记录清除掉,来保存新记录,似乎完美解决了问题。
在TLB和Page Table加持之下,CPU感受最近MMU比较给力了,就问MMU怎么作到的?MMU就一五一十告诉了CPU。
CPU说是个不错的路子,随后说出了本身的建议:TLB仍是有点小,缓存不命中也是常常发生的,要不要搞个大的,这样存储更多访问更快?
MMU一脸苦笑说道大哥TLB很贵的,要不你给涨点外包费?话音未落,CPU就说涨工资是不可能了,这辈子都不可能了。
>>>高能预警 敲黑板 本段小结<<<
1. CPU要根据用户进程提供的虚拟地址来获取真实数据,可是它并不本身作而是交给了MMU。2. MMU也是个聪明的家伙,集成了TLB来存储CPU最近经常使用的页表项来加速寻址,TLB找不到再去全量页表寻址,能够认为TLB是MMU的缓存。
3. TLB的容量毕竟有限,为此必须依靠Page Table一块儿完成TLB Miss状况的查询,而且更新到TLB创建新映射关系。
设想CPU给MMU的虚拟地址在TLB和Page Table都没有找到对应的物理页帧或者权限不对,该怎么办呢?
没错,这就是缺页异常Page Fault,它是一个由硬件中断触发的能够由软件逻辑纠正的错误。
假如目标内存页在物理内存中没有对应的页帧或者存在但无对应权限,CPU 就没法获取数据,这种状况下CPU就会报告一个缺页错误。
因为CPU没有数据就没法进行计算,CPU罢工了用户进程也就出现了缺页中断,进程会从用户态切换到内核态,并将缺页中断交给内核的 Page Fault Handler 处理。
缺页中断会交给PageFaultHandler处理,其根据缺页中断的不一样类型会进行不一样的处理:
不一样类型的Page Fault出现的缘由也不同,常见的几种缘由包括:
>>> 敲黑板 划重点 本段小结:<<<
触发Page Fault的缘由可能有不少,归根到底也只有几种大类:1. 如使用共享内存区域,没有存储VA->PA的映射可是存在物理页帧的软缺页错误,在Page Table/TLB中创建映射关系便可。
2. 访问的地址在物理内存中确实不存在,须要从磁盘/swap分区读入才能使用,这种性能影响会比较大,由于磁盘太慢了,尽可能使用高性能的SSD来下降延时。
3. 访问的地址内存非法,缺页错误会升级触发SIGSEGV信号结束进程,这种属于能够致使进程挂掉的一种缺页错误。
本文粗浅地和你们一块儿学习了Page Fault的相关知识点,包括Linux虚拟地址和物理地址的关系、CPU获取内存数据的过程、MMU和TLB&页表的协同配合、缺页异常产生的缘由和分类处理。
本文并无对MMU的内部机制、内核态&用户态缺页异常、缺页异常处理函数等内容进行展开,主要是由于这部份内容相对晦涩,还得靠本身深刻研究。
本文旨在把火点燃而不是把桶填满,对于文中相关知识点,欢迎交流沟通学习。
感谢各位老铁的倾情安排,下期再见!