当前位置: 首页 > news >正文

【Kernel】Linux CFS(完全公平调度器)实现原理与机制

Linux CFS(完全公平调度器)实现原理与机制

目标:系统讲解 CFS 的核心理念、关键数据结构、主要函数路径与抢占/选取规则,结合源码位置与图示帮助快速理解与复核。

代码树:kernel-4.4.94


1. 设计理念与核心概念

  • 目标:以“虚拟运行时间”(vruntime)度量公平,将每个可运行实体按权重在时间上趋于平均。
  • 核心思想:
    • 按任务权重(nice 与组权重)累积 vruntime:运行越久,vruntime 增长越多;权重越大,单位真实时间贡献到 vruntime 的增量越小(体现更高权重的任务更“慢”积累,因而更频繁被选中,以保持公平)。
    • 在每 CPU 的 cfs_rq 红黑树上,选择 vruntime 最小的实体运行(红黑树最左节点)。
  • 重要参数与影响:
    • sched_latency:期望在一个窗口内让所有任务都至少运行一次。
    • min_granularity:最小运行粒度,防止任务过短导致调度开销过高。
    • wakeup_granularity:唤醒抢占的“跨越阈值”,防止过度抢占。

1.1 权重与 vruntime 的关系(为什么“权重高更慢积累”会更公平)

  • CFS 用 vruntime 作为排序依据:vruntime 越小越容易被选中(红黑树最左)。
  • 运行时给 vruntime 的增量与权重成“反比”,典型近似公式:
    • delta_vruntime = delta_exec * NICE_0_LOAD / se->load.weight
      • delta_exec:本次实际运行的真实时间
      • NICE_0_LOAD:nice=0 的基准权重(典型为 1024)
      • se->load.weight:该任务权重(由 nice 映射;nice 越小权重越大)
  • 解释:权重高(nice 小)的任务在相同真实时间内,vruntime 增量更小;因此它更长时间停留在“更左”的位置,更频繁被选中运行,最终实现“按权重分配”真实 CPU 时间的公平。

示例(两任务 A/B):

  • A:nice=0 → weight_A = 1024
  • B:nice=+5 → weight_B ≈ 335
  • 每次运行 1ms 的 vruntime 增量:
    • A:delta_vruntime_A = 1ms * 1024 / 1024 = 1ms
    • B:delta_vruntime_B = 1ms * 1024 / 335 ≈ 3.06ms
  • 直觉:A 增长慢(更常在左边被选),B 增长快(更快“被推到右边”),长期真实 CPU 时间比例约为 1024 : 335(约 75% : 25%)。

补充:

  • CFS 不用固定时间片;而是用 min_granularity 保证最小运行时间,并用 sched_latency 控制一个窗口内的“轮转期望”。
  • 在一个窗口中,每任务“应得运行量”近似于 sched_period * (weight_i / total_weight);实际选取则由 vruntime 排序推动,二者一致性通过“慢积累→更常被选”的机制实现。

2. 数据结构与关键字段(kernel/sched/fair.c

  • struct cfs_rq(每 CPU 的 CFS 运行队列):
    • 红黑树:存放 struct sched_entity(简称 se)集合,按 se->vruntime 排序。
    • min_vruntime:队列的最小 vruntime 基线,用于放置新实体与归一化比较。
    • 统计字段:负载、权重总和等,用于计算 slice 与迁移决策。
  • struct sched_entity(任务或组的调度实体):
    • vruntime:虚拟运行时间,调度公平性的核心度量。
    • 链到红黑树的 rb_entry
    • task_struct 关联(或与调度组 cgroup 的层级实体关联)。

3. 主要函数路径与行为

  • 入队:enqueue_task_fair(rq, p, flags)(约 4160–4260)
    • 更新统计、调用层级的 enqueue_entity(),将 se 插入红黑树;按 flags(如 ENQUEUE_WAKEUP)标记唤醒场景。
  • 出队:dequeue_task_fair(rq, p, flags)
    • 从红黑树移除实体,更新队列统计。
  • 放置:place_entity(cfs_rq, se, initial)(约 2950–3010)
    • cfs_rq->min_vruntime 为基线;首次入队可能应用 START_DEBIT 的“预借”,避免新任务过度领先;唤醒场景按 sched_latency 做温和奖励(GENTLE_FAIR_SLEEPERS)。
  • 选择:pick_next_task_fair(rq)(约 5280–之后)
    • 选取红黑树的最左节点(最小 vruntime 的实体),并设置为当前运行实体(set_next_entity())。
  • 抢占:check_preempt_wakeup(rq, p, wake_flags)(约 5120–5360)
    • 若当前为 SCHED_IDLE 而新任务非 idle,必抢占;
    • 比较 vdiff = curr->se.vruntime - p->se.vruntimewakeup_granularity(经 wakeup_preempt_entity),差距足够则 resched_curr(rq)
    • 启发式 NEXT_BUDDY/LAST_BUDDY 促进交互响应与局部性。
  • 更新:update_curr(cfs_rq) / entity_tick(cfs_rq, se) / task_tick_fair(rq, p, current)
    • 在时钟 tick 中为当前实体累积 vruntime;必要时触发重插入或切换。
  • 选核:select_task_rq_fair(p, ...)kernel/sched/fair.ckernel/sched/core.c 协同)
    • 在 SMP 下依据均衡域选择合适 CPU,考虑负载与亲和性;wake_up_new_task() 中也会进行 SD_BALANCE_FORK 路径的选核。

4. CFS 的抢占与响应性机制

  • 唤醒抢占:
    • 新任务被唤醒时,与当前运行任务比较 vruntime 差值,若跨越 wakeup_granularity 则触发立刻抢占,保障交互式任务响应。
  • 轮转与时间片:
    • CFS不使用固定时间片;以 min_granularity 控制最小运行时间,配合 sched_latency 与权重确保在一个窗口内各任务获得运行机会。
  • 组与权重:
    • 任务所属组按照权重分配时间份额;组内再按成员权重分配,形成层级公平。

5. 机制图(SVG)与树形示意

  • 队列与选取(红黑树最左):

在这里插入图片描述

  • 唤醒抢占与 wakeup_granularity

在这里插入图片描述


6. 关键参数与调优提示

  • sched_latency_ns:窗口长度;任务数多时会自动扩展以保证每任务至少一次运行机会。
  • sched_min_granularity_ns:最小粒度,避免过短运行导致调度开销偏高。
  • sched_wakeup_granularity_ns:唤醒抢占阈值;越大越保守,越小越激进(更快抢占)。
  • sched_child_runs_firstSTART_DEBIT:影响新任务首次放置与响应性。
  • 交互工作负载优化:适度降低 wakeup_granularity,启用 LAST/NEXT_BUDDY 有助于提升响应。

7. 源码索引(4.4.94)

  • kernel/sched/fair.c
    • place_entity()(~2994)
    • enqueue_task_fair()(~4184) / dequeue_task_fair()
    • check_preempt_wakeup()(~5168)
    • pick_next_task_fair()(~5280+)
    • update_curr() / entity_tick() / task_tick_fair()
  • kernel/sched/core.c
    • check_preempt_curr()(~1027)
    • wake_up_new_task()(~2390–2460)
    • select_task_rq()(~1638)
  • include/linux/sched.h / kernel/sched/sched.h
    • 调度类定义、struct rq/cfs_rq/sched_entity 等结构。

8. 小结

  • CFS 以 vruntime 作为公平性核心,围绕红黑树最左选取与权重归一,在 sched_latency 窗口内实现相对公平的 CPU 时间分配;
  • 唤醒抢占与最小粒度共同平衡响应性与吞吐;
  • 理解关键函数与参数能帮助调试“任务响应慢”和“调度抖动”等问题。
http://www.dtcms.com/a/574473.html

相关文章:

  • Alibaba Cloud Linux 3 安装 Tomcat
  • 什么自查询?为什么在 RAG 中需要自查询?
  • 做早餐煲汤网站wordpress移动端顶部导航栏
  • 地坪漆东莞网站建设技术支持做淘宝的人就跟做网站一样
  • Vue 用户管理系统(路由相关练习二)
  • 三维建筑非法入侵情景推演
  • 新加坡建设局网站企业网站策划过程
  • 工程师报考网站企业站系统
  • Agent 设计与上下文工程- 03 Workflow 设计模式(下)
  • 硅基计划6.0 JavaEE 壹 多线程及核心内容
  • 网站建设+三乐seo优化系统哪家好
  • 游戏网站建设收费明细自己怎么制作假山
  • 调用模型的两个参数 temperature 和 max_new_tokens 指什么
  • Deepseek在它擅长的AI数据处理领域还有是有低级错误【k折交叉验证中每折样本数计算】
  • 影刀RPA实时监控抖店DSR评分,AI预警异常波动,店铺权重稳如泰山![特殊字符]
  • 用html做的美食网站wordpress 自动空格
  • 网站防护找谁做wordpress创建搜索框
  • 【雷达跟踪滤波例程】3个雷达的三维目标跟踪滤波系统,目标匀速运动,滤波为扩展卡尔曼|雷达观测:斜距、俯仰角、方位角。MATLAB,附下载链接
  • Go红队开发—图形化界面
  • 测开百日计划——Day1
  • 一些工具的使用
  • MATLAB多子种群混沌自适应哈里斯鹰算法优化BP神经网络回归预测
  • 红外体温产品开发踩坑后,我发现谷德 0.05℃精度的红外体温芯片居然自带免费算法?
  • 周口师范做网站好的网站建设网
  • 无锡网站wordpress 3.8.1
  • 巫山做网站哪家强wordpress 升级提示
  • 探索 MCP 生态与边缘智能体部署的家常话
  • 商城网站建设推广手机网站特效代码
  • MIT-0-1背包问题
  • AI+近红外:实现粮食质量快速检测的智能化升级——从单指标到多指标同步预测的技术飞跃