Linux CFS调度器(Completely Fair Scheduler,完全公平调度器)是Linux内核中默认的进程调度算法,自2.6.23版本引入,旨在以高效、公平的方式分配CPU时间。本文将从零讲解CFS的核心思想、工作原理,并结合内核源码(基于5.x版本)解析关键实现,即使是初学者也能轻松理解。
在Linux系统中,进程调度决定了哪个进程获得CPU使用权。CFS摒弃了传统的时间片轮转,采用基于虚拟运行时间的动态优先级模型,通过红黑树组织可运行进程,每次选择虚拟时间最小的进程执行,从而保证所有进程的公平性。
虚拟运行时间(vruntime)是CFS的灵魂。每个可运行的进程都有一个vruntime,它记录进程实际运行时间的加权值。权重由进程优先级(nice值)决定:nice值越低,权重越高,vruntime增长越慢,从而获得更多CPU时间。CFS使用红黑树将所有可运行进程按vruntime排序,最左侧节点(vruntime最小)就是下一个要运行的进程。
调度周期(sched_latency)内,CFS尽力让每个进程运行至少一次。当进程运行时,其vruntime随着实际时间增加,增加速度与权重成反比。被调度出去的进程,其vruntime被维护在红黑树中,下次调度时选择vruntime最小的。这种设计保证了所有进程的vruntime基本接近,实现“完全公平”。
如果进程睡眠或唤醒,其vruntime会进行调整(通常不更新,或补偿一些值),防止睡眠进程被饥饿。此外,CFS还支持组调度(task group),将进程分组管理,组间也按相同原则分配CPU。
在Linux内核源码中,与CFS相关的主要数据结构定义在 和 中。
se 字段(sched_entity类型),即调度实体,存储vruntime、权重等信息。struct rq 中):每个CPU的运行队列,包含红黑树根节点 tasks_timeline、最小vruntime min_vruntime 等。enqueue_task_fair() 将进程插入树中,dequeue_task_fair() 移除,pick_next_task_fair() 选取最左侧节点。核心函数 update_curr() 更新当前进程的vruntime,并维护cfs_rq的min_vruntime。关键代码如下(简化):
static void update_curr(struct cfs_rq *cfs_rq){ struct sched_entity *curr = cfs_rq->curr; u64 now = rq_clock_task(rq_of(cfs_rq)); u64 delta_exec = now - curr->exec_start; curr->vruntime += calc_delta_fair(delta_exec, curr); curr->exec_start = now; // 更新最小vruntime if (cfs_rq->nr_running) update_min_vruntime(cfs_rq);} 其中 calc_delta_fair() 根据权重将实际执行时间转换为虚拟时间。权重越大,虚拟时间增加越慢。
CFS调度器通过虚拟运行时间和红黑树,以简单而优雅的方式实现了多任务环境下的公平调度。理解其原理有助于优化应用性能、排查调度相关问题,也为深入学习Linux内核打下基础。本文涉及的CFS调度器、Linux内核、进程调度、虚拟运行时间四个关键词是掌握CFS的核心,希望读者能从中获益。
本文由主机测评网于2026-03-10发表在主机测评网_免费VPS_免费云服务器_免费独立服务器,如有疑问,请联系我们。
本文链接:http://www.vpshk.cn/20260330205.html