Linux 调度流程分析(2) 之主调度函数

主调度流程

__schedule() 函数

主调度的函数原型为 static void __schedule(unsigned int sched_mode)

  • 该主调度函数在内部执行了任务选择、任务切换的主要工作;
  • 参数 sched_mode 可以为:
    • SM_NONE:无特殊的调度模式
    • SM_PREEMPT:可抢占的调度模式
    • SM_RTLOCK_WAIT:等待实时锁的调度模式

调度主流程

  • 调度是针对每个 CPU 的,所以首先要获取当前 CPU 的运行队列;

  • 运行到此处,说明任务实际已经没有在运行(实际运行的是调度程序),所以停掉运行队列的 hrtick

  • 调度的过程需要关闭本地中断;

  • 上报 RCU 的静止状态,以及清除当前任务持有的 RCU 信息 —— RCU 锁不允许跨调度持有;

  • 下面要操作运行队列了,这里首先要对运行队列上锁;而且要使用内存写屏障来保证在以下操作之前,前面的操作已经完成,防止由于乱序执行造成的竞争问题;

  • 如果 rq 设置了跳过时钟统计请求就将其升级为忽略时钟统计——这里采用了移位的方式来做标志位的更改;

  • 更新 rq 的时间戳和运行时间;

  • 获取当前进程的状态;

  • 当当前任务是自愿调度时:

    • 如果有待处理的信号时,保持当前任务为 TASK_RUNNING 状态;

    • 否则根据是否要将当前任务计算到 rq 的负载,来更新 rq 的不可中断任务的数量;

    • 将任务去激活:

      • 标记任务的 on_rq 的状态;
      • 将任务从运行队列上出队;
    • 如果当前任务处于 iowait ,增加 rq 等待 io 的数量;

    • 更新当前任务的切换(自愿调度/非自愿调度)统计;

  • 选择下一个待运行的任务;

  • 因为要进行任务选择已经完成,这时可以清除重新调度标记和抢占标记;

  • 在任务切换前,存在两种情况:

    • 选择的下一个任务不是当前任务;

      • 更新运行队列的切换次数;
      • 更新运行队列的当前任务指针;
      • 更新当前进程切换次数;
      • 禁止当前任务迁移;
      • 切换压力任务切;
      • 进行上下文切换 —— 此时 CPU 资源就让渡给新的任务;
    • 选择的下一个任务就是当前任务;

      • 清除 rq 的忽略时钟更新标志;
      • 进行一次负载均衡

任务的 on_rq 状态:

  • 0:如果为 “0” 表示此任务没有在运行队列上;
  • TASK_ON_RQ_QUEUED :此任务在运行队列上;
  • TASK_ON_RQ_MIGRATING:此任务正在迁移中;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值