2.6.2.1 调度逻辑 - 数据结构
不管是O(n)还是O(1), 调度器采用的都是列表来组织任务,O(n)将所有的任务都放在一个列表中,每次调度时都需要遍历所有节点;O(1)采用了多级列表,不同的列表通过优先级来划分,显著地提高了查找效率。由于CFS在调度时只需要选择vruntime最小的节点,因此CFS选择了红黑树(Red-Black Tree)这种更高效的数据结构来管理任务,红黑树的Key就是vruntime, 这样红黑树最左子节点永远都是下一个需要调度的任务。
红黑树是二叉查找树(BST - Bianry Search Tree)的一种,其特点是在对树节点进行增加、删除操作时能够尽可能地保持平衡,这样可以保证即使在最坏的情况下,总体的时间复杂度都保持在对数级别。这里我们不对红黑树做深入讨论,感兴趣的读者可以自行查阅资料。
Linux中黑红树的实现在文件
lib/rbtree.c
中,此处有详细介绍:https://lwn.net/Articles/184495/
CFS 使用调度实体 sched_entity
来封装调度时需要的各种属性,删除组调度与统计信息后代码如下:
CFS 定义了自己的运行队列 cfs_rq
, 同样删除额外字段后内容如下:
为什么需要保存 min_vruntime
呢?CFS 每次调度都选择 vruntime 最小的进程来运行,试想一下当系统创建一个新的进程时,如何给该进程初始化 vruntime 呢?正常来说该任务还没有运行过,所以该值应该为0, 但如果这样的话该进程的 vruntime 将远远小于队列中所有的任务,它将一直霸占 CPU 运行下去直到 vruntime 追上队列中其它任务,而这显然是不合理的。因此我们需要一个方法来对这些情况进行调节,该方法就是 min_vruntime
, 后续我们将介绍详细的调节方式。
总体而言,CFS的核心数据结构关系如下:
Last updated
Was this helpful?