高 进阶
上下文切换开销#
一句话答案#
上下文切换保存/恢复 CPU 寄存器,进程切换还需切换页表导致 TLB 失效(有 PCID/ASID 时可不整体刷新);线程切换比进程快,协程比线程更快。
核心要点
开销来源:
- 保存/恢复 CPU 寄存器
- 进程切换:页表切换 + TLB 失效(无 PCID/ASID 时整体刷新;x86 Linux 4.14 起用 PCID 可保留带标签的表项)
- Cache 冷启动
量级: 直接开销(进内核、保存恢复、调度)进程和线程都在 1数微秒;进程切换额外的主要代价是 TLB/Cache 冷启动这类间接开销,算上后可到数十微秒,和工作集大小强相关
减少: 协程(用户态调度) / 线程池(复用线程) / IO多路复用(减少线程数)
面试回答(2分钟版)
上下文切换是操作系统在不同执行单元之间切换时保存和恢复 CPU 状态的过程。切换时需要保存当前执行单元的寄存器值、程序计数器、栈指针等到内存中的 PCB 或 TCB,然后加载目标执行单元之前保存的状态。进程切换的开销最大,除了寄存器保存恢复外还需要切换页表,页表切换会导致 TLB 缓存失效(没有 PCID/ASID 时要整体刷新),后续的内存访问都要重新做地址翻译,再加上 CPU Cache 冷启动,算上这些间接开销一次进程切换可能到数十微秒。线程切换的开销小得多,因为同一进程内的线程共享地址空间不需要切换页表,只需要保存恢复线程私有的寄存器和栈,直接开销大约数微秒,但它依然要陷入内核、走调度器。协程切换开销最小,它完全在用户态完成不需要陷入内核,几百纳秒级别。在实际工程中减少上下文切换的常见手段有:使用线程池复用线程避免频繁创建销毁、使用 IO 多路复用减少线程数量、使用协程替代线程、使用无锁数据结构减少锁竞争导致的阻塞切换。可以通过 vmstat 命令的 cs 列监控系统的上下文切换次数。
追问与易错
追问方向:
- “怎么减少上下文切换?”→ 线程池复用线程、IO 多路复用减少线程数、协程替代线程(用户态切换)、无锁数据结构(CAS)减少阻塞切换、CPU 亲和性绑定
- “怎么监控切换次数?”→
vmstat的 cs 列看系统级切换、pidstat -w看进程级切换、/proc/PID/status的 voluntary/nonvoluntary_ctxt_switches - “自愿和非自愿切换区别?”→ 自愿切换是进程主动让出 CPU(如 IO 等待、sleep),非自愿切换是被调度器强制抢占(时间片用完、高优先级抢占)
易错点:
- ❌ 上下文切换开销可忽略——高频时显著影响性能
- ❌ 线程切换不进内核——内核线程切换同样要陷入内核、走调度器,只是省了换页表;真正不进内核的是协程
- ❌ 进程切换慢主要慢在保存寄存器——寄存器保存只是几十纳秒级,大头是 TLB/Cache 失效后的访存变慢