协程和线程的上下文切换详解

上下文切换

什么是上下文切换?上下文切换的时机?
CPU通过分配时间片来执行任务,当一个任务的时间片用完,就会切换到另一个任务。在切换之前会保存上一个任务的状态,当下次再切换到该任务,就会加载这个状态。
——任务从保存到再加载的过程就是一次上下文切换。

按导致上下文切换的因素划分,可将上下文切换分为两点:

  • 自发性上下文切换
  • 非自发性上下文切换

自发性上下文切换指线程由于自身因素导致的切出。

非自发性上下文切换指线程由于线程调度器的原因被迫切出。如:

切出线程的时间片用完
有一个比切出线程优先级更高的线程需要被运行
虚拟机的垃圾回收动作

上下文切换的开销

上下文切换的开销包括直接开销和间接开销。
直接开销有如下几点:

  1. 操作系统保存回复上下文所需的开销
  2. 线程调度器调度线程的开销

间接开销有如下几点:

  1. 处理器高速缓存重新加载的开销
  2. 上下文切换可能导致整个一级高速缓存中的内容被冲刷,即被写入到下一级高速缓存或主存

 

协程切换

协程切换只涉及基本的CPU上下文切换,所谓的CPU上下文,其本质就是一堆寄存器,里面保存了CPU运行任务所需要的信息:

  • 从哪里开始运行((%rip:指令指针寄存器°,标识CPU运行的下一条指令)
  • 栈顶的位置(%rsp:是堆栈指针寄存器°,通常会指向栈顶位置)
  • 当前栈帧在哪(%rbp是栈帧指针,用于标识当前栈帧的起始位置)
  • 以及其它的CPU的中间状态或者结果(%rbx,%r12,%r13,%14,%15等等

协程切换非常简单,就是把当前协程的CPU寄存器状态保存起来,然后将需要切换进来的协程的CPU寄存器状态加载的CPU寄存器上就 ok了。

而且完全在用户态进行,一般来说一次协程上下文切换最多就是几十ns这个量级
切换流程:

  1. 每个线程都对应这一个TCB,TCB中有一个TSS字段,存储着线程对应的内核栈的地址,也就是内核栈的栈顶指针
  2. 因为从用户态切换到内核态时,首先用户态可以直接读写寄存器,用户态操作CPU,将寄存器的状态保存到对应的内存中,然后调用对应的系统函数,传入对应的用户栈的PC地址和寄存器信息,方便后续内核方法调用完毕后,恢复用户方法执行的现场。
  3. 将CPU的字段改为内核态,将内核段对应的代码地址写入到PC寄存器中,然后开始执行内核方法,相应的方法栈帧时保存在内核栈中。
  4. 当内核方法执行完毕后,会将CPU的字段改为用户态,然后利用之前写入的信息来恢复用户栈的执行。

从上述流程可以看出用户态切换到内核态的时候,会牵扯到用户态现场信息的保存以及恢复,还要进行一系列的安全检查,比较耗费资源。

为什么线程切换会导致用户态与内核台的切换?

因为线程的调度是在内核态运行的,而线程中的代码是在用户态运行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值