1.什么是CPU上下文切换

就是先把前一个任务的CPU上下文(也就是CPU寄存器和程序计数器)保存起来,然后加载新任务的上下文到这些寄存器和程序计数器,最后再跳转到程序计数器所指的新位置,运行新任务。

根据任务不同,CPU的上下文切换可以分为不同的场景:进程上下文切换、线性上下文切换以及中断上下文切换

1.进程上下文切换

Linux按照特权等级,把进程的运行空间分为内核空间和用户空间。

fc830619f46aa068b19d58260658ac4c.png

  1. 内核空间(Ring 0)具有最高权限,可以直接访问所有资源
  2. 用户空间(Ring 3)只能访问受限资源,不能直接访问内存等硬件设备,必须通过系统调用陷入到内核中,才能访问这些特权资源

从用户态到内核态的转变,需要通过系统调用来完成;一次系统调用过程,发生了两次CPU上下文切换

进程上下文切换,是指从一个进程切换到另一个进程运行。而系统调用过程中一直是同一个进程在运行。

  1. 系统调用过程通常称为特权模式切换,而不是上下文切换
  2. 进程的上下文切换就比系统调用时多了一步:在保存当前进程的内核状态和 CPU 寄 存器之前,需要先把该进程的虚拟内存、栈等保存下来;而加载了下一进程的内核态后, 还需要刷新进程的虚拟内存和用户栈。

进程在什么时候才会被调度到cpu上运行?

  1. 为了保证所有进程公平调度,CPU时间被划分为一段段时间片,被轮流分配给各个进程(进程结束就被系统挂起,切换给其他进程)
  2. 进程在系统资源不足时,要等到资源满足后才可以运行,这是个进程也会被挂起,并有系统调度其他进程运行
  3. 当进程通过睡眠函数sleep方法主动挂起,自然也会重新调度
  4. 当有优先级更高的进程运行时,为了保证高优先级进程的运行,当前进程也会被挂起
  5. 当硬件中断时,cpu上饿进程会被中断挂起,转而执行内核中的中断服务进程

2.线程上下文切换

线程与进程最大的区别在于,线程是调度的基本单位,而进程则是资源拥有的基本单位。 说白了,所谓内核中的任务调度,实际上的调度对象是线程;而进程只是给线程提供了虚 拟内存、全局变量等资源。所以,对于线程和进程,我们可以这么理解:

  1. 当进程只有一个线程时,可以认为进程就等于线程。
  2. 当进程拥有多个线程时,这些线程会共享相同的虚拟内存和全局变量等资源。这些资源 在上下文切换时是不需要修改的。 另外,线程也有自己的私有数据,比如栈和寄存器等,这些在上下文切换时也是需要保 存的。

线程的上下文切换其实就可以分为两种情况:

  1. 前后两个线程属于不同进程。此时,因为资源不共享,所以切换过程就跟进程上 下文切换是一样。
  2. 前后两个线程属于同一个进程。此时,因为虚拟内存是共享的,所以在切换时, 虚拟内存这些资源就保持不动,只需要切换线程的私有数据、寄存器等不共享的数据。

3.中断上下文切换

为了快速响应硬件的事件,中断处理会打断进程的正常调度和执行,转而调用中断处理程 序,响应设备事件。

  • 跟进程上下文不同,中断上下文切换并不设计进程的用户态。
  • 中断处理比进程拥有更高的优先级