每个任务执行前,CPU 都需要知道任务从哪里加载、又从哪里开始运行,也就是说,需要系统事先帮它设置好 CPU 寄存器和程序计数器。
寄存器内置在CPU内,是容量小,速度快的内存。
计数器则是用来存储 CPU 正在执行的指令位置、或者即将执行的下一条指令位置。
他们是CPU执行指令时所依赖的环境,所以叫做CPU上下文。
一个CPU可以执行多个任务,使用了时间分片。
举个栗子:将1秒分成5份,每一份0.2秒。现有3个任务:A,B,C,每个任务执行完成需要1秒
一个CPU先执行0.2秒的任务A,任务A没有执行完,就将任务A目前的相关状态保存起来。
然后加载任务B的相关状态,执行0.2秒的任务B,任务B没有执行完,就将任务B目前的相关状态保存起来。
接着加载任务C的相关状态,执行0.2秒的任务C,任务C没执行完,将任务C的目前状态保存起来。
然后又返回头加载任务A前面保存的状态,继续执行0.2秒的任务A,然后A又没执行完,继续保存任务A的相关状态,依次类推下去。
每一次保存未完成任务的相关状态,加载后续要执行任务的相关状态,这一保存一加载,就成为是CPU上下文切换。
CPU上下文切换是很耗性能的,进程和线程的执行都涉及到上下文的切换,太多的切换会导致CPU的飙升。
有很多其他场景,也会触发进程调度,在这里简单梳理下:
其一,为了保证所有进程可以得到公平调度,CPU 时间被划分为一段段的时间片,这些时间片再被轮流分配给各个进程。这样,当某个进程的时间片耗尽了,就会被系统挂起,切换到其它正在等待 CPU 的进程运行。
其二,进程在系统资源不足(比如内存不足)时,要等到资源满足后才可以运行,这个时候进程也会被挂起,并由系统调度其他进程运行。
其三,当进程通过睡眠函数 sleep 这样的方法将自己主动挂起时,自然也会重新调度。
其四,当有优先级更高的进程运行时,为了保证高优先级进程的运行,当前进程会被挂起,由高优先级进程来运行。
最后一个,发生硬件中断时,CPU 上的进程会被中断挂起,转而执行内核中的中断服务程序。