以Q&A的方式:
一条指令在流水线的过程?
指令首先进入流水线(pipeline)的前端(front-end),包括预取(fetch)和译码(decode),经过分发(dispatch)和调度(schedule)后进入执行单元,最后提交执行结果。
所有的指令采用顺序方式通过前端,并采用乱序的方式进行发射,然后乱序执行,最后用顺序方式提交执行结果。
既然指令是顺序提交结果,那为什么还需要内存屏障?
在CPU0上执行下面操作:
data = 1; // 操作1
flag = 1; // 操作2
在单核的角度上,乱序执行 + 顺序提交 确保了单核程序的局部正确性。
在多核的角度上,由于MESI协议的store buffer特性和invaild queue特性,可能会先观察到flag=1,后观察到data=1,从而误读旧data值。
顺序提交的必要性?
Inst1 执行中触发异常(如缺页、除零),尚未执行的 Inst2 必须处于未提交状态,以便异常处理完成后可回滚到一致的程序状态)。寄存器重命名技术的概念?
寄存器重命名技术能够消除 假性依赖(寄存器读后写相关(Write-after-Read ,WAR )和写后写相关(Write-after-Write,WAW)),允许更多指令乱序执行,最大化利用处理器流水线的并行能力,但无法消除真性依赖(RAW(写后读))。
WAR例子:
ADD R1, R2, R3 ; R1 = R2 + R3 (读 R2、R3,写 R1)
MUL R2, R4, R5 ; R2 = R4 * R5 (读 R4、R5,写 R2)
分析:因为指令2要写R2,指令1需要读R2,所以造成了WAR依赖。若 指令2 因乱序执行先完成,指令1 将读取被覆盖后的错误 R2 值。
解决:修改指令2的目标寄存器为P2,则消除了WAR冲突。
WAW例子:
MUL R1, R2, R3 ; R1 = R2 * R3 (写 R1)
ADD R1, R4, R5 ; R1 = R4 + R5 (写 R1)
**分析:**理想情况下,指令2 结果应覆盖 指令1,但是在乱序执行的情况下,R1会被污染,导致最终结果错误。
**解决:**将指令1的R1改为P1,指令2的R1改为P2。
分支预测于likely()有关吗?
**分支预测技术(动态技术)**与likely()/unlikely()宏的关联性主要体现在 编译器的静态优化 层面,而非硬件动态分支预测的直接控制。
likely(x) 宏的本质是通过 __builtin_expect 提示编译器 分支的更可能走向,从而在编译阶段优化指令布局:
if (likely(x)))排列在程序顺序的前端,增加其被预取到指令缓存(ICache)的概率。这个跟冷热代码布局有关。
内存屏障产生的原因?
内存乱序访问主要发生在如下两个阶段:
(1)编译时,编译器优化导致内存乱序访问。 (2)执行时,多个CPU 间交互引起的内存乱序访问。
编译器造成的内存屏障怎么解决?
编译时的乱序访问可以通过barrier()函数来规避。这个是静态的。
多个CPU间交互引起的内存乱序访问怎么解决?

SMP:多核。UP:单核。
rmb()和smp_rmb()的区别是什么,分别用在什么场景?
smp_rmb()仅针对多核的数据共享,而rmb()可能涉及更广泛的域(如系统级,比如说DMA),因此后者开销更大。内核未启用CONFIG_SMP(即单核编译)时,smp_rmb()可能退化为编译器屏障(barrier()),而rmb()仍会生成硬件屏障指令。
| 场景 | 使用屏障 | 原因 |
|---|---|---|
| 多核间的读顺序同步(如自旋锁) | smp_rmb() |
仅需约束 CPU 核间的读顺序,开销小(dmb ishld)。 |
| 设备驱动的 DMA 操作 | rmb() |
需约束 CPU 和设备间的读顺序,必须用全系统屏障(dmb sy)。 |
| 单核环境但需硬件屏障 | rmb() |
smp_rmb() 在单核编译时可能退化为空操作,而 rmb() 始终生成硬件指令。 |
单片机什么场景下需要内存屏障?
单独写一篇文章。
Linux下的READ_ONCE和WRITE_ONCE的作用?
READ_ONCE和WRITE_ONCE是编译器屏障+轻量级内存屏障,等同于volatile+LDAR 。
PIPT ,VIVT ,VIPT 的区别?
在查询cache时,到底用虚拟地址还是物理地址?
- VIVT:使用虚拟地址的索引域和虚拟地址的标记域,相当于虚拟高速缓存。
- PIPT:使用物理地址的索引域和物理地址的标记域,相当于物理高速缓存。
- VIPT:使用**虚拟地址的索引域**和**物理地址的标记域**。
**PIPT**:

**VIVT**:

**VIPT:**

处理器输出的**虚拟地址会同时发送到TLB/MMU 进行地址翻译**,以及在高速缓存中进行索引和查询高速缓存。在TLB/MMU 里,会把VPN 翻译成PFN,**同时用虚拟地址的索引域和偏移量来查询高速缓存**。高速缓存和TLB/MMU 可以同时工作,**当TLB/MMU 完成地址翻译后,再用物理标记域来匹配高速缓存行**。

虚拟高速缓存引入的问题?
VIVT容易引入重名问题和同名问题。
重名问题:多个不同的虚拟地址映射到同一个物理地址。造成cache浪费和缓存一致性问题。
同名问题:相同的虚拟地址在不同进程中映射到不同的物理地址。经常出现在进程切换时,进程可能会访问到旧进程遗留的缓存数据,这些数据对新进程来说是错误的。
MESI协议的作用?
MESI协议是用于维护多核处理器缓存一致性的核心机制,确保多个CPU核心对同一内存位置的访问不会导致数据冲突或脏数据问题。
MESI协议的4种状态?
MESI协议的状态转换?
场景:4个CPU访问同一数据A