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

CFS 的调度类型:普通调度 vs 组调度

在Linux的完全公平调度器(CFS)中,普通调度(默认模式)和组调度(Group Scheduling)是两种互补的任务组织方式,主要区别在于资源分配的层次结构和公平性控制的范围。以下是它们的对比与实现细节:


1. 普通调度(默认CFS)

  • 核心思想:以**单个任务(task)**为调度单位,所有任务在统一的公平队列(cfs_rq)中竞争CPU时间。
  • 关键特性
    • 公平性目标:通过虚拟运行时(vruntime)保证每个任务获得平等的CPU时间比例(权重调整除外)。
    • 权重(nice值):通过task_struct->se.load权重区分任务优先级(nice -2019)。
    • 调度单位:每个任务独立计算vruntime,红黑树中选择最小vruntime的任务运行。
  • 局限性
    • 若某用户或进程组启动大量任务,会挤占其他用户/组的资源(如用户A运行100个进程,用户B运行1个进程,B可能被“饿死”)。

2. 组调度(CFS Group Scheduling)

  • 核心思想:引入**任务组(task_group)**作为调度单位,实现层级公平性(Hierarchical Fair Scheduling)。
  • 关键特性
    • 层级化调度实体
      • 每个任务组拥有自己的cfs_rq和调度实体(sched_entity),组内任务共享组的vruntime
      • 组之间按权重分配CPU,组内再按任务权重分配(双层公平)。
    • 控制组(cgroups)集成:通过cpu控制器(如cpu.shares)动态调整组权重。
    • 资源隔离:防止单个用户或容器垄断CPU。
  • 实现示例
    # 创建CPU控制组并设置权重
    mkdir /sys/fs/cgroup/cpu/groupA
    echo 512 > /sys/fs/cgroup/cpu/groupA/cpu.shares  # 默认1024,groupA获得50% CPU
    
  • 优势场景
    • 多用户系统(如云服务器)中保障用户间公平性。
    • 容器化环境(Docker/Kubernetes)中限制容器的CPU配额。

3. 对比总结

特性普通调度组调度
调度单位单个任务(task_struct任务组(task_group
公平性层次全局任务间公平组间公平 + 组内任务公平
资源控制仅通过nice调整任务权重通过cgroups控制组权重(cpu.shares
适用场景单用户桌面环境多租户服务器、容器集群
红黑树组织全局一棵cfs_rq红黑树每个组维护独立的cfs_rq

4. 底层实现关键点

  1. 组调度的数据结构

    • task_group结构体包含组的cfs_rqse(调度实体)。
    • 任务组的se会被加入父组的cfs_rq,形成层级树。
    // 内核结构示例(简化)
    struct task_group {struct cfs_rq cfs_rq;      // 组自己的CFS运行队列struct sched_entity se;    // 组作为调度实体unsigned long shares;      // 权重(通过cpu.shares设置)
    };
    
  2. 调度决策流程

    • 从根cfs_rq开始,递归选择vruntime最小的组或任务。
    • 组间选择依赖组的se.vruntime,组内选择任务的se.vruntime
  3. 权重分配公式

    • 组间CPU比例 = group.shares / parent.shares_sum
    • 组内任务CPU比例 = task.load / group.load_sum

5. 性能与调试

  • 开销:组调度因层级管理会增加少量开销(尤其在深度嵌套的cgroups时)。
  • 调试工具
    • cat /proc/sched_debug:查看所有cfs_rqsevruntime
    • systemd-cgtop:实时监控cgroups的CPU使用率。

通过组调度,CFS实现了从单任务公平到多级资源控制的扩展,成为现代Linux系统资源管理的基石。

http://www.xdnf.cn/news/600.html

相关文章:

  • 【中级软件设计师】语言处理程序(汇编程序、解释程序、编译程序)附软考真题
  • go语言优雅关机和优雅重启笔记
  • WEMOS LOLIN32
  • 第一部分笔试Day_01到Day24_每天两道OJ
  • 图解MCP:Model Context Protocol
  • 从零开始用Pytorch实现LLaMA 4的混合专家(MoE)模型
  • 【Java】接口interface学习
  • 国际数据加密算法(IDEA)详解
  • CentOS 10 /root 目录重新挂载到新分区槽
  • 【数据结构入门训练DAY-18】信息学奥赛一本通T1331-后缀表达式的值
  • URLDNS链构造
  • Android Studio 中 Drawable 详细全解
  • Android Drawable 目录下的 XML 图形文件详解
  • 在 Linux 上部署 .NET Core 应用并配置为开机自动启动
  • [操作系统] 信号
  • GO语言入门:常用数学函数2
  • rollup使用讲解
  • JUC复习及面试题学习
  • SpringBoot 统一功能处理
  • 智谱开源新一代GLM模型,全面布局AI智能体生态
  • 墙面刷完乳胶漆之后就有裂缝,有根治的办法吗?
  • Java面向对象进阶
  • BEVDet: High-Performance Multi-Camera 3D Object Detection in Bird-Eye-View
  • 年化26.9%的稳健策略|polars重构因子计算引擎(python策略下载)
  • AI——神经网络以及TensorFlow使用
  • 《汽车理论》第四章作业MATLAB部分
  • 传统深度学习架构和Transformer结构的区别
  • 从0开始搭建一套工具函数库,发布npm,支持commonjs模块es模块和script引入使用
  • uniapp-商城-29-vuex 关于系统状态的管理
  • 嵌入式单片机开发问题:Undefined symbol _HAL_RCC_GPIOB_CLK_ENABLE