CPU寄存器,与程序计数器(存储CPU正在执行的指令位置,或者即将执行的下一条指令的位置)共同组成CPU上下文。
CPU上下文切换指的是:把前一个任务的CPU上下文保存起来,然后加载新任务的上下文到这些寄存器和程序计数器上,最后再跳转到程序计数器所指的新位置,运行新的任务。被保存下来的上下文会存储在系统内核中,等任务重新调度执行时再次加载进来。
根据任务的不同,CPU的上下文切换可以分为几个不同场景(进程上下文切换、线程上下文切换、中断上下文切换)
进程上下文切换
系统调用:
已知进程运行空间分为内核空间和用户空间。内核空间可以访问所有资源,用户空间只能访问受限资源,不能访问内存等硬件设备。
从用户态到内核态的转变需要通过系统调用来完成。如open、read、write、close 等对于文件的操作都属于系统调用。
系统调用的过程中会发生CPU上下文切换,先切换到内核态,执行内核态代码,再跳转回用户态代码。所以一次系统调用会发生两次CPU上下文切换,又称特权模式切换,不过仍然是同一个进程在运行。
进程上下文切换性能问题:
进程由内核管理和调度,进程的切换只能发生在内核态,进程上下文不仅包括虚拟内存、栈、全局变量等用户空间资源,还包括内核堆栈、寄存器等内核空间状态。每次进程上下文切换需要几十纳秒到数微秒的CPU时间。
并且Linux通过TLB来管理虚拟内存到物理内存之间的映射,当虚拟内存更新后,TLB也需要刷新,内存的访问也会随之变慢。特别在多处理器系统上,缓存被多个处理器共享,刷新缓存不仅会影响当前处理器的进程,还会影响共享缓存的其他处理器的进程。
进程上下文切换发生的时机:
在进程调度的时候,需要进行切换上下文。Linux为每个CPU维护一个就绪队列,将活跃进程(正在运行和正在等待CPU的进程)
按照优先级和等待CPU的时间来排序,然后选择最需要CPU的进程运行。(优先级高和等待时间长的进程)
1、CPU时间被划分为一段段时间片,当某个进程的时间片耗尽,就会被系统挂起,切换到其他正在等待的进程
2、进程在系统资源不足时,要等到资源满足后才可以运行,此时这个进程也会被挂起,CPU让给其他进程
3、进程通过sleep睡眠函数主动挂起,CPU让给其他进程
4、当有优先级更高的进程运行,当前进程会被挂起
5、发生硬件中断,CPU进程会被中断挂起,执行内核中的中断服务程序
进程上下文切换
线程是调度的基本单位,而进程是资源拥有的基本单位。当进程中只有一个线程时,可以认为进程就等于线程。
当进程拥有多个线程时,这些线程会共享相同的虚拟内存和全局变量等资源。
线程主要就是私有数据、栈和寄存器等资源。
线程上下文切换分为两种情况:
1、两个线程属于不同线程,资源不共享,所以等同于进程上下文切换
2、两个线程属于同一个进程,只需要切换私有数据、寄存器等不共享的数据
中断上下文切换
与系统调用不同,中断上下文切换不涉及进程的用户态。所以中断过程打断了一个正处于用户态的进程,也不需要保存和恢复这个进程的虚拟内存、全局变量等用户资源。它只包括内核态中断服务程序执行所必须的状态:CPU寄存器、内核堆栈、硬件中断参数
|