彻底理解Linux 进程调度所有知识点( 五 )

  1. delta_exec = now - curr->exec_start; 计算出当前CFS运行队列的进程 , 距离上次更新虚拟时间的差值
  2. curr->exec_start = now; 更新exec_start的值
  3. curr->sum_exec_runtime += delta_exec; 更新当前进程总共执行的时间
  4. 通过 calc_delta_fair 计算当前进程虚拟时间
  5. 通过 update_min_vruntime 函数来更新CFS运行队列中最小的 vruntime 的值
pick_next_entitypick_next_entity 函数会从就绪队列中选择最适合运行的调度实体(虚拟时间最小的调度实体) , 即从 CFS 红黑树最左边节点获取一个调度实体 。
static struct sched_entity *pick_next_entity(struct cfs_rq *cfs_rq, struct sched_entity *curr){ struct sched_entity *left = __pick_first_entity(cfs_rq);    ------(1) struct sched_entity *se; /*  * If curr is set we have to see if its left of the leftmost entity  * still in the tree, provided there was anything in the tree at all.  */ if (!left || (curr && entity_before(curr, left)))  left = curr; se = left; /* ideally we run the leftmost entity */ /*  * Avoid running the skip buddy, if running something else can  * be done without getting too unfair.  */ if (cfs_rq->skip == se) {  struct sched_entity *second;  if (se == curr) {   second = __pick_first_entity(cfs_rq);                   ------(2)  } else {   second = __pick_next_entity(se);                        ------(3)   if (!second || (curr && entity_before(curr, second)))    second = curr;  }  if (second && wakeup_preempt_entity(second, left) < 1)   se = second; } /*  * Prefer last buddy, try to return the CPU to a preempted task.  */ if (cfs_rq->last && wakeup_preempt_entity(cfs_rq->last, left) < 1)  se = cfs_rq->last; /*  * Someone really wants this to run. If it's not unfair, run it.  */ if (cfs_rq->next && wakeup_preempt_entity(cfs_rq->next, left) < 1)  se = cfs_rq->next; clear_buddies(cfs_rq, se); return se;}
  1. 从树中挑选出最左边的节点
  2. 选择最左的那个调度实体 left
  3. 摘取红黑树上第二左的进程节点
put_prev_entityput_prev_entity 会调用 __enqueue_entity 将prev进程(即current进程)加入到 CFS 队列 rq 上的红黑树 , 然后将 cfs_rq->curr 设置为空 。
static void __enqueue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se){ struct rb_node **link = &cfs_rq->tasks_timeline.rb_root.rb_node; //红黑树根节点 struct rb_node *parent = NULL; struct sched_entity *entry; bool leftmost = true; /*  * Find the right place in the rbtree:  */ while (*link) {                                ------(1)  parent = *link;  entry = rb_entry(parent, struct sched_entity, run_node);  /*   * We dont care about collisions. Nodes with   * the same key stay together.   */  if (entity_before(se, entry)) {              ------(2)   link = &parent->rb_left;  } else {   link = &parent->rb_right;   leftmost = false;  } }   rb_link_node(&se->run_node, parent, link);     ------(3) rb_insert_color_cached(&se->run_node,          ------(4)          &cfs_rq->tasks_timeline, leftmost);}


推荐阅读