前言:
在这个补给站,我稍微简单介绍一下处理器中的一些架构(设计上的一些小trick),顺便再来讲讲保护模式到底保护了哪些东西
一,处理器微架构
①,流水线
流水线大家肯定经常听说过,富士康工厂经常就做这种事情,比如一个工人要砸钉子这一操作,我们可以把他看作流水线工作。
我们先将其分为两步:取钉子和砸钉子,执行每一步操作需要1s。如果按顺序工作
那么每砸一个钉子就是2s的时间。
- 流水线与并行
但是我们把整个流程的两步分给不同的人去做,比如师傅A做砸钉子,师傅B负责取钉子,那么便会有下面的结果:
我们可以看到,在4s内砸了三颗钉子,比之前的顺序执行整整多了一颗,而且在后续也是平均1s钟产生一颗钉子。
问:
哪有人可能就会说,为什么不用并行呢,并行的吞吐量甚至还大于流水线的吞吐量
- 吞吐量:
并行2s生成2个,4s就是4个
流水线2s生成1个,后面每s1个,第4s就是3个可以看出流水线的生成是要有产量损耗的
- 时间频率:
并行生成第3颗钉子需要等到4s
流水线生成第3颗钉子只需要等到3s
并行的吞吐量是大于流水线的吞吐量的,但是流水线的执行频率以及指令处理时间是要优于并行的
上述论证,对于CPU来说是很重要的,因为指令最重要的是执行那一步,如果将一个指令执行的全过程分为很多很多步(在cpu中称为分级),那么在流水线形成后,一个指令就可以以很快的频率执行!
流水线清空#执行如下指令 jmp 某个函数地址 mov ax,4 add bx,ax
在jmp指令进行到执行的一步时,由于流水线的特性,第二条和第三条指令已经被装入流水线,但是jmp的跳转是跳转到一个与后续指令毫不相关的地方,所以这个时候2,3指令已经没用了,执行完jmp 就会清空流水线,重新载入
②,乱序处理
乱序执行即,当两行代码毫无联系时,就会颠倒执行顺序,以加快指令执行。
mov eax,[0x1234] add ecx,ebx
第一条指令需要去内存取值,这一步是很耗时间的,且eax,ecx,ebx之间无联系,便会将第二条指令和第一条指令倒转顺序。(学过java volatile应该会十分熟悉)
- 指令集与乱序
有两种指令集,CISC(复杂指令集计算机),RISC(精简指令集计算机)。
CISC:有多个微指令集合成一个指令
RISC:遵循二八定律,存放了微指令,即不可再细分的指令
现在大多数都是采用RISC的内核,再编译CISC的指令时会将其分为RISC指令,由于指令与指令间微不可分,独立无关联,非常适合乱序执行。
③,缓存
缓存这个我们在之前聊过很多了,对于CPU这种高速设备来说内存的速度已经无法满足他了,他需要一个速度更快的存储器,那就是缓存。也便诞生了L1缓存,L2缓存,L3缓存,他们都是SRAM,和寄存器都是触发电路所以速度都十分的快,至于谁更快没有具体了解,总之都是纳秒激别。
- 什么时候缓存?
1,根据局部性原理来判断
空间局部性:靠近当前内存空间的内存地址,将来一段时间也会被访问
时间局部性:最近访问过的指令和数据,将来也会被访问
④,分支预测
分支就是我们平常看到的if和else,我们执行到分支需要再加载分支代码到流水线的时候不可能同时加载两边的分支,因为最终只会用到一个分支,这个时候就要采取分支预测算法。
- 预测算法:
2位预测法(最简单的现在基本上以这个位基层):用2 bit 计数器记录跳转次数,这个分支每跳转一次就+1否则-1,>3&<0就不+ -了,当遇到跳转指令时,会检查计数器,如果计数器>0就不跳转了。
- CPU的实现:
CPU采用了BTB分支目标缓冲器,CPU遇到分支时便用分支指令的地址在BTB中查找,找到则送到流水线上面并且更新BTB的,没找到就进入静态预测器
静态预测器即存放人们总结出来的写死的特征规律
如:循环跳转
当发现转移地址低于当前地址,那么会认为是循环回路。
- 预测错了咋办?
很简单清空流水线即可,反正指令没有执行,不用担心
二,保护模式对内存段的保护
有人看完day 5保护模式的介绍后,可能会想,保护模式到底保护了谁呢?保安虽然保护不了任何人,但是保护模式还是可以保护一些东西的。
① 对段寄存器加载选择子的保护
当段寄存器加载某个选择子时会进行如下检查:
- 选择子T1的值,来拉取GDT或者LDT
- 根据GDT或者LDT的界限,来对照选择子高13位是否超界限
- 对于GDT来说索引值不能为0
- 找到对应的段描述符,检查type(太多了,我直接贴图,不一定要记下来,开发的时候看看)
- 查看P确认内存段是否存在,如果存在就会将选择子放入段寄存器中
② 对代码段和数据段的保护
访问内存要采取分段策略,不管是指令还是数据都是有长度的,根据分段的规定,不管是数据还是代码都不能骑在段边界上
代码段满足:EIP的偏移地址+指令长度-1 <= 实际段界限大小
数据段满足:偏移地址+数据长度-1 <= 实际段界限大小
③ 栈段的保护
这个我也没太看懂,所以就不误人子弟了,我发个图方便以后开发的时候对照对照。