CPU上下文切换
CPU上下文:
任务可以运行,是因为一些具有CPU寄存器和程序计数器等硬件条件的CPU上下文环境的支撑。CPU寄存器是CPU内置的容量非常小但是速度极快的存储设备,程序计数器则是CPU在运行任何任务时必要的,里面记录了当前运行任务的行数等信息,这就是CPU上下文
上下文切换分类
CPU的上下文切换就可以分为进程上下文切换、线程上下文切换、中断上下文切换
进程上下文切换
在服务器中,进程的运行空间可以分为内核空间和用户空间,内核空间具有最高权限,可以直接访问内存、硬盘等资源,而用户空间,只能访问受限的用户资源,要想访问内存等,需要通过系统调用的方式实现
用户态进入内核态的一种方式就是系统调用,而系统调过程中,同样发生了CPU的上下文切换(CPU寄存器里面原来用户态的指令位置,需要先保存起来,接着运行内核态代码;CPU寄存器需要更新为内核态指令的位置,执行内核态代码)
在系统调用结束后,cpu寄存器需要恢复原来保存的用户态,然后切换为用户空间,所以,一次系统调用的过程中,就会发生两次CPU上下文切换
进程上下文在切换的过程中,操作系统需要先存储当前进程的状态(包括内存空间的指针,当前执行完的指令等等),再读入下一个进程的状态,然后执行此进程
为什么说系统调用是特权模式切换,而不是上下文切换:
这里说的上下文的切换,是指进程的上下文切换,进程是有系统内核管理和调度的,进程的切换只能发生在内核态,所以,进程的上下文包含了虚拟内存、栈、全局变量等用户空间的资源,还包含了内存堆栈、寄存器等内核空间的状态,但是系统调用并没有涉及到虚拟内存等这些进程用户态的资源,也不会切换进程,只是单纯的进程内的上下文切换,
性能对比:
因为进程的上下文切换要比系统调用更多一步,即保存改进程的虚拟内存、栈等用户空间资源,而一次进程上下文切换一般需要几十纳秒到数微秒的CPU时间,所以,当进程的上下文切换次数较多的情况下,将导致cpu在寄存器、内存栈(虚拟内存)等资源的保存和回复上耗费大量时间,另外,Linux通过TLB快表来管理虚拟内存到物理内存的映射关系,当虚拟内存更新之后,需要刷新缓存,在这多处理系统上是很复杂的,因为多个处理器共享一个缓存。故此,综合而言,大量的进程上下文切换会降低系统性能
线程上下文切换
线程是调度的基本单位,而进程则是资源拥有的基本单位,也就是说对于内核中的任务调度是以线程为单位,但是进程只是给线程提供了虚拟内存、全局变量等资源
线程的上下文切换分两种:
① 前后两个线程属于不同进程,因为资源不共享,所以这时候的线程上下文切换和进程上下文切换是一致的
② 前后两个线程属于同一个进程,因为虚拟内存是共享的,所以在切换的时候,虚拟内存这些资源保持不动,只有切换线程的私有数据、寄存器等不共享的资源
综上,线程上下文切换比进程上下文切换系统消耗更少
中断上下文切换
中断是为了快速响应硬件的事件,简单来shu就是计算机停下当前的事情,去处理其他的事情,然后在回来继续执行之前的任务
当然,中断要先将当前进程的状态保存下来,这样中断结束后进程仍然可以从原来的状态恢复运行,中断上下文的切换并不涉及进程的用户态,所以当中断程序打断了正在处于用户态的进程,不需要保存和恢复这个进程的虚拟内存、全局变量等用户态资源,只需要保存和恢复这个进程的内核态中的资源包括CPU寄存器、内核堆栈等对于同一个CPU来说,中断处理比进程拥有更高的优先级,所以中断上下文切换并不会与进程上下文切换同时发生,一般来说中断程序都执行比较快短小精悍,以便快速结束执行之前的任务。当中断上下文切换次数比较多的时候,会耗费大量的CPU
为何进程上下文切换比线程上下文切换成本高
进程切换分两步:
1.切换页目录以使用新的地址空间
2.切换内核栈和硬件上下文
对于linux来说,线程和进程的最大区别就在于地址空间,对于线程切换,第1步是不需要做的,第2是进程和线程切换都要做的。
切换的性能消耗:
1、线程上下文切换和进程上下问切换一个最主要的区别是线程的切换虚拟内存空间依然是相同的,但是进程切换是不同的。这两种上下文切换的处理都是通过操作系统内核来完成的。内核的这种切换过程伴随的最显著的性能损耗是将寄存器中的内容切换出。
2、另外一个隐藏的损耗是上下文的切换会扰乱处理器的缓存机制。简单的说,一旦去切换上下文,处理器中所有已经缓存的内存地址一瞬间都作废了。还有一个显著的区别是当你改变虚拟内存空间的时候,处理的页表缓冲等都会被全部刷新,这将导致内存的访问在一段时间内相当的低效。但是在线程的切换中,不会出现这个问题