Linux 调度流程分析(3) 之上下文切换

上下文切换

上下文切换是实际资源的所有权转让发生的地方。这里更多的考虑是硬件相关的实际操作,例如 tlb 的切换、内存的释放等。

主要流程:

  • 切换前的准备工作
    • 将下一个任务的 on_cpu 状态设置为 1;
    • 代码覆盖率切换;
    • 统计任务在队列上的等待时间;
    • perf 性能计时器的切换;
    • 发送 sched out 抢占通知;
    • 32 位系统中高端内存的映射切出;
    • 构架相关的准备工作;
  • 切换开始时,CPU 构架需要做的工作;
  • 当下一个任务是内核任务时(内核任务没有用户态部分的内存)
    • 告诉内核不需要进行 tlb 切换;
    • 借用上个任务的用户态内存;
      • 如果上个任务为用户任务,则增加内存的引用计数器,防止上个任务退出时将内存释放掉;
      • 如果上个任务也是内核任务,则直接将内存转交给下个任务;
  • 当下一个任务是用户任务时:
    • 同步内存屏障状态;
    • 切换 tlbmmu 和加载页表;
    • 如果上个任务是内核任务:
      • rq->prev_mm 中记录该任务——上个任务会清除 active_mm 记录,而该块内存所属的任务有可能已经退出,所以在这里需要由 rq 来进行记录并在后续释放;
      • 清除上个任务的 active_mm
  • 清除 rq 的时钟的统计跳过标记;
  • 进行实际的上下文切换:
    • 变更内核栈(用户部分已经在 switch_mm 部分变更);
    • 切换寄存器的内容;
  • 在执行最后部分之前插入内存屏障,保证之前的指令都已经完成;
  • 调用 finish_task_switch() 函数对上个任务进行最后的处理,该函数与之前的 prepare_task_switch() 函数成对使用:
    • 修正抢占计数器;
    • 统计上个任务的 idle/system 时间;
    • 到这里前一个任务已经被切出 CPU 这里需要更新上个任务的 on_cpu 状态;
    • 重新评估 nohz 状态,检查是否需要重新启用定时器;
    • 做一次负载均衡;
    • 调用构架相关的函数在上下文切换完成后进行一些处理工作;
    • 代码覆盖率切换;
    • 处理高端内存的映射切入;
    • 发送 sched in 通知,表明任务切换已经完成;
    • 如果上个任务死亡:
      • 调用上个任务调度类的 task_dead() 函数做后续处理,例如 cfs 调度类会删除该任务对应的负载贡献值;
      • 处理上个任务的引用计数器;
      • 延迟释放 bpf & perf 使用的内存空间;

任务的上下文切换主要做四件事情:

  • 切换进程的空间,也即虚拟内存;
  • 切换寄存器和 CPU 资源;
  • 标记任务状体( on_cpu );
  • 以及死亡任务的后续处理;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值