之前文章linux内核fork剖析分析了fork模式创建进程。其中在copy_process函数中sched_fork主要实现父子进程的时间片分割。本文主要分析linux调度器之CFS的逻辑,包括调度算法和数据结构等。有益于linux内核学习者对linux的CPU调度有一定的认识和熟悉。
task_fork是一个函数指针,实际调用的是fair_sched_class的task_fork_fair函数,位于文件kernel/sched/fair.c中。
每个cpu的运行队列 CFS运行队列,cfs_rq->tasks_timeline是个RB-Tree
CFS调度实体 CFS调度器涉及到的RB-Tree结构在include/linux/rbtree.h task_fork_fair函数 update_curr函数主要是更新队列调度时间
update_min_vruntime()函数保证就绪队列的最小虚拟时间min_vruntime单调递增的特性,更新最小虚拟时间。
继续分析place_entity函数
惩罚值计算逻辑:
do_fork的初始化工作就完成了。接下来就是将进程加入就绪队列,等待唤醒调度。
wake_up_new_task函数
enqueuer_task_fair函数
接下来重点分析入队函数enqueue_entity: accout_entity_enqueue函数更新就绪队列相关信息
接下来就是check_preempt_curr函数:检查是否满足抢占条件 情况1:唤醒的进程和当前running的进程属于同一个调度类,例如CFS
Check_preempt_curr实际是回调函数,对应函数是check_preemt_wakeup
情况2:唤醒的进程和当前running进程不属于同一个调度类,例如唤醒进程属于RT,当前running进程属于CFS
总结:本文主要介绍CFS实现细节,对于学习linux 内核有比较好的帮助,尤其在定位系统级问题时大有裨益。另外,学习linux内核也能获取不少系统设计方面的知识,包括算法和一些数据结构,为以后系统设计和编码上面提供参考。