上一篇聊一聊linux的cpu调度器CFS,我们已经分析了进程创建之后是如何设置相应数据项以及是否进行抢占调度等逻辑。除了进程创建会涉及到CFS,周期性调度也会使用到CFS。
周期性调度是指Linux定时周期性地检查当前任务是否耗尽当前进程的时间片,并检查是否应该抢占当前进程。一般会在定时器的中断函数中,通过一层层函数调用最终到scheduler_tick()函数。
由于调用task_tick的struct是sched_class,因此对应的回调函数是task_tick_fair update_curr函数已经在上一篇文章中分析过来,因此本文重点分析check_preemt_tick函数。
针对周期性调度可以总结为:
1、更新正在运行进程的虚拟时间
2、检查当前进程是否满足被抢占,满足则将从就绪队列挑选运行时间最小的进程;将被强占的进程重新加入到RB-tree中;从RB-tree中删除即将运行的调度实体。
如何选择下一个合适进程运行
__schedule核心逻辑:
put_prev_task最终回调put_prev_task_fair.
看下put_prev_task_fair的实现逻辑。
put_prev_task_fair函数里主要逻辑是put_prev_entity函数,看下put_prev_entity函数的实现逻辑。
prev进程的已经处理完毕,接下来就是调用set_next_entity函数更新即将运行的调度实体
在__schedule()函数中,如果prev进程主动睡眠。那么会调用deactivate_task()函数。deactivate_task()函数最终会调用调度类dequeue_task方法。CFS调度类对应的函数是dequeue_task_fair(),该函数是enqueue_task_fair()函数反操作。
dequeuer_task_fair函数
总结:本文主要是继上一篇CFS调度的续篇,主要阐述了CFS的周期性调度逻辑。对于了解CPU调度逻辑(包括进程什么时候被调度,什么时候被强占,调度时的状态,未调度时的状态,数据存储、计算和更新等知识有一个整体的概念和把握)。另外,理解CPU调度逻辑对于系统问题排查也很有帮助。