为什么操作系统进行上下文切换时不会保存TLB内容?
为什么操作系统不在进程控制块中保存TLB内容
你的核心判断偏差是错误估算了保存/恢复TLB的实际开销,以及TLB miss的真实影响范围,这套设计从硬件逻辑、投入产出比、现有成熟方案三个维度看,都完全不具备可行性:
- 首先绝大多数硬件根本没给软件读写全量TLB表项的接口,且TLB是核心私有资源
TLB是每个CPU核心独立的微架构级缓存,和L1/L2缓存一样为纳秒级访问延迟设计,x86、ARM等绝大多数通用架构根本没提供遍历、读取当前所有有效TLB表项的指令,操作系统连TLB里当前存了什么内容都读不到,自然谈不上保存。就算少数嵌入式架构支持软件读写TLB,一方面软件逐条读写表项的延迟极高,远不是“一点小开销”的级别;另一方面进程调度时不一定会回到上次运行的核心,不同核心的TLB条目格式、支持的页类型都可能存在差异,存下来的快照根本没法跨核心恢复。 - 其次保存TLB的性能账完全算不过来
现在主流消费级、服务器级CPU的TLB规模并不小:L1指令/数据TLB各有3264项4K页条目,L2共享TLB通常有5122048项条目,全量保存要读写上千条记录。但进程被调度切回CPU的时候,根本不会立刻访问到之前用到的所有内存页——程序运行有极强的局部性,刚恢复执行时只会访问当前栈、运行时代码段、核心工作集的几十个页,对应的TLB条目加起来也就几十项,剩下上百个条目在进程下一次被切走之前可能根本不会被访问,全量恢复纯属做无用功。
算个直白的账:一次普通TLB miss(页表遍历命中CPU缓存)的成本大概是几十纳秒,你花时间恢复1000个永远用不到的TLB项的时间,足够处理上百次实际发生的TLB miss,属于纯赔本操作。 - 现有硬件+OS方案比保存TLB到PCB的效率高几个数量级
现在根本不需要靠“转存TLB”解决上下文切换的TLB miss问题:- 所有内核页的TLB条目都带全局标记,上下文切换刷TLB时根本不会被清空,这部分占TLB相当大比例的条目完全不需要重新加载
- 现代CPU都支持ASID/PCID(地址空间标识符),TLB条目会直接标记所属的进程ID,上下文切换时不需要清空TLB,只要把CPU当前运行的地址空间ID改成新进程的就行,老进程的TLB条目会一直留在TLB里直到被缓存替换算法踢走,等进程切回来的时候直接就能用,比从内存PCB读回TLB快了好几个数量级
- 大页(2M/1G)的普及进一步压缩了TLB miss的概率,单个TLB条目能覆盖的内存范围是4K页的512倍/262144倍,绝大多数业务场景下TLB miss率本身就低到可以忽略。
- 最后TLB内容本身是瞬态易失效的
TLB存的是虚拟地址到物理地址的临时映射,进程被切出CPU的这段时间里,它的物理内存页可能被迁移、被换出到交换分区、被内存回收机制作废,之前存的TLB快照里的物理地址早就失效了,恢复回去反而会触发内存访问错误,还要额外加校验逻辑,又是一笔没必要的开销。
补充:只有在几十年前TLB只有个位数条目、没有硬件ASID支持的特殊实时系统上,才出现过上下文切换保存TLB的设计,这套方案在现代通用计算场景下早就被淘汰了。
内容的提问来源于stack exchange,提问作者n66
相关产品推荐
相关产品推荐

