CPU上下文切换
什么是CPU上下文切换
问题:一台单核linux主机,进程竞争CPU,竞争时候并没有运行进程,为什么会导致平均负载
升高呢?
回答:Linux 是一个多任务操作系统,它支持远大于 CPU 数量的任务同时运行,但是同一个时间内多个任务并没有同时运行,是系统用很短时间在多个任务不断切换(上下文切换)给我们同时运行的假象,之所以平均负载
升高是因为CPU 上下文切换需要在寄存器、内核栈以及虚拟内存等数据的保存和恢复上,过多的CPU上下文切换导致缩短进程真正运行的时间,导致系统的整体性能大幅下降,平均负载
升高
CPU上下文切换:就是先把前一个任务的CPU上下文(也就是 CPU 寄存器和程序计数器)保存起来,然后加载下一个任务的上下文到这个寄存器和程序计数器,最后再跳转到程序计数器所指的新位置,运行新任务。
- CPU寄存器:是CPU内置容量小,但是速度极快的内存
- 程序计数器:是用来存储CPU正在执行指令的位置,或者是执行下一条指令的位置
CPU上下文切换并不是只切换了CPU 寄存器的值。
下面介绍CPU根据不同任务
切换的场景以及切换时候做的事情
- 进程上下文切换
- 线程上下文切换
- 中断上下文切换
进程和线程的区别
首先我们介绍下进程和线程的区别
- 进程是资源拥有的基本单元
- 线程是调度是基本单元
通过进程来请求系统资源,然后进程中的线程来调度执行任务
进程上下文切换
特权模式切换
Linux 按照特权等级,把进程的运行空间分为内核空间和用户空间,分别对应着下图中, CPU 特权等级的 Ring 0 和 Ring 3。

内核空间(Ring 0):具有最高权限,可以直接访问所有资源;
用户空间(Ring 3):只能访问受限资源,不能直接访问内存等硬件设备,必须通过系统调用陷入到内核中,才能访问这些特权资源。
进程可以在用户空间运行为用户态,又可以在内核空间运行为内核态。
进程从用户态切换到内核态是通过系统调用
来完成,该过程也是有CPU山下问切换的
- 切换时先保存CPU寄存器中的用户态指令
- 再重新更新内核态指令位置
- 最后跳转到
内核态
运行内核任务 - 当
系统调用
结束后需要恢复
原来保存的用户态
一次系统调用
中,其实发生了两次CPU上下文切换
系统调用
:并不会涉及虚拟内存,等用户态的资源保存,也不会涉及切换进程
- 进程上下文切是指,一个进程切换到另一个进程
- 系统调用是一直在同一个进程中运行的切换
所以 系统调用
一般称为特权模式切换
,而不是上下文切换,但是系统调用
中还是无法避免CPU上下文切换的
进程上下文切换介绍
进程上下文切是指,一个进程切换到另一个进程
所以进程上下文切换其实是比特权模式切换
多了一步:在保存当前进程的内核状态和CPU寄存器之前,需要把用户态该进程的虚拟内存,栈等保存下来,然后加载下一个进程到内核态后,还需要刷新进程和虚拟内存和用户栈

Linux 通过 TLB(Translation Lookaside Buffer)来管理虚拟内存到物理内存的映射关系。当虚拟内存更新后,TLB 也需要刷新,内存的访问也会随之变慢。特别是在多处理器系统上,缓存是被多个处理器共享的,刷新缓存不仅会影响当前处理器的进程,还会影响共享缓存的其他处理器的进程。
linux为每个CPU维护了一个就绪队列,按照优先级和等待CPU的时间排序,也就是优先级最高的和等待CPU时间最长的进程优先使用CPU
触发进程切换的场景
-
为了保证进程得到公平的调度,CPU时间片,依次分配给每个进程,当一个某个进程时间片耗尽了,就会被挂起,切换到下一个进程。
-
进程在系统资源不足时,需要等系统资源满足后才可以运行,这时候进程就会被挂起,并切换到其它进程。
-
当进程通过睡眠函数 sleep 这样的方法将自己主动挂起时,也会切换到其它进程。
-
当有优先级更高的进程运行时,为了保证高优先级进程的运行,当前进程会被挂起,由高优先级进程来运行。
线程上下文切换
当进程只有一个线程时,可以认为进程就等于线程。
当进程拥有多个线程时,这些线程会共享相同的虚拟内存和全局变量等资源。这些资源在上下文切换时是不需要修改的。
另外,线程也有自己的私有数据,比如栈和寄存器等,这些在上下文切换时也是需要保存的。
线程上下文切换分为两种
-
一个进程下多个线程的切换,因为虚拟内存是共享的,所以在切换时,虚拟内存这些资源就保持不动,只需要切换线程的私有数据、寄存器等不共享的数据。
-
两个进程下的线程切换:线程分布在两个进程中,资源不共享,所以和进程切换相同
中断上下文切换
为了快速响应硬件的事件,中断处理会打断进程的正常调度和执行,而在打断其他进程时,就需要将进程当前的状态保存下来,这样在中断结束后,进程仍然可以从原来的状态恢复运行
跟进程上下文不同,中断上下文切换并不涉及到进程的用户态
跟进程上下文不同,中断上下文切换并不涉及到进程的用户态。所以,即便中断过程打断了一个正处在用户态的进程,也不需要保存和恢复这个进程的虚拟内存、全局变量等用户态资源
对同一个 CPU 来说,中断处理比进程拥有更高的优先级
总结
- 特殊权限切换是在同一个进程内产生的CPU上下文切换。
- 进程上下文切换会涉及CPU寄存器,虚拟内存,内核栈保存恢复操作,所以较多的进程上下文切换会导致切换时间都耗费在恢复资源,挂起资源中,减少进程运行时间,导致性能问题。
- 同进程内线程上下文切换因为数据为共享的,所以只涉及私有数据、寄存器切换,不同进程中线程上下文切换和进程上下文切换相同。