调度器之任务分组

任务分组

我们先看以下两种场景。

(1)执行<font style="color:rgb(0,0,0);">make -j10</font>(选项<font style="color:rgb(0,0,0);">-j10</font>表示同时执行 10 条命令),编译 Linux 内核,同时运行视频播放器,如果给每个进程平均分配 CPU 时间,会导致视频播放很卡。

(2)用户 1 启动 100 个进程,用户 2 启动 1 个进程,如果给每个进程平均分配 CPU 时 间,用户 2 的进程只能得到不到 1%的 CPU 时间,用户 2 的体验很差。

怎么解决呢?把进程分组。对于第一种场景,把编译 Linux 内核的所有进程放在一个任务组 中,把视频播放器放在另一个任务组中,给两个任务组分别分配 50%的 CPU 时间。对于第二种场景,给用户 1 和用户 2 分别创建一个任务组,给两个任务组分别分配 50%的 CPU 时间。


任务分组(Task Group) 是对进程进行逻辑划分和资源限制管理的一种机制,主要用于 控制资源使用、调度策略、统计 等目的。

任务分组的实现核心是 cgroup(Control Groups)子系统,以及调度器中的 task_group 结构体

struct task_group

/* task group related information */
struct task_group {
	struct cgroup_subsys_state css;

#ifdef CONFIG_FAIR_GROUP_SCHED
	/* schedulable entities of this group on each cpu */
	struct sched_entity **se;
	/* runqueue "owned" by this group on each cpu */
	struct cfs_rq **cfs_rq;
	unsigned long shares;
#endif

#ifdef CONFIG_RT_GROUP_SCHED
	struct sched_rt_entity **rt_se;
	struct rt_rq **rt_rq;

	struct rt_bandwidth rt_bandwidth;
#endif
    ...
};
    
  • 每个 task_group 表示一个进程组。
  • 每个 task_group 对应一个调度实体数组(se)和一个运行队列(cfs_rq)等。
  • task_groupcgroup 是一一对应的(由 css 连接)。
  • 每个进程的 task_struct 中会关联其所属的 task_group

调度器中的任务分组支持

Linux 支持多个调度器,比如:

  • CFS(完全公平调度器)
  • RT(实时调度器)

每种调度器都有对应的 task group 处理逻辑,例如:

  • cfs_rq:表示该 task_group 的 CFS 调度运行队列。
  • rt_rq:表示该 task_group 的实时调度运行队列。
  • 对每个 CPU,调度器会在其上为每个 task_group 创建对应的运行队列。

调度时,内核会根据任务所属的 group,在其 group 的运行队列中进行选择,这样可以实现任务分组的公平调度和资源限制。


CPU运行队列和task_group中运行队列的关系

CPU 的运行队列(per-CPU runqueue)

每个 CPU 上维护一个独立的运行队列:

struct rq {
    struct cfs_rq cfs;  // 默认调度器 CFS 的运行队列
    struct rt_rq rt;    // 实时调度器的运行队列
    ...
    };

这个 rq 是每个 CPU 的调度核心数据结构,调度器总是在该 CPU 的 rq 上操作任务。


task_group 的运行队列(per-task_group runqueue)

task_group 的核心在于它为 每个 CPU 创建自己的调度子队列,例如:

struct task_group {
    struct cfs_rq **cfs_rq;         // 所有 CPU 上本组的 CFS 队列数组
    struct sched_entity **se;       // 本组在上一级 group 中的调度实体
    ...
};
  • tg->cfs_rq[cpu] 表示该任务组在第 cpu 核心上的 CFS 运行队列。
  • tg->se[cpu] 表示该任务组在父组中代表自身的调度实体(可嵌套)。

这形成了一个分组树结构:组嵌套 -> 组调度实体 -> 组运行队列


任务组在每个处理器上有公平调度实体、公平运行队列、实时调度实体和实时运行队列,根任务组比较特殊:没有公平调度实体和实时调度实体。

(1)任务组的下级公平调度实体加入任务组的公平运行队列,任务组的公平调度实体加入上级任务组的公平运行队列。

(2)任务组的下级实时调度实体加入任务组的实时运行队列,任务组的实时调度实体 加入上级任务组的实时运行队列。


运行队列之间的关系图

以 CFS 调度器为例,关系如下图:

每个 CPU:
rq (CPU0)
├── cfs_rq                      // CPU 的根调度队列
│   ├── se (A组调度实体) ─┐
│   ├── se (B组调度实体) ─┐│
│                         ││
│                         ▼▼
│                   task_group_A.cfs_rq[CPU0]
│                   task_group_B.cfs_rq[CPU0]
  • 每个 CPU 的 rq.cfs 是顶层队列,里面的 sched_entity 可以是单个任务,也可以是一个组。
  • 如果是组的 sched_entity,就指向该组的 cfs_rq[cpu]
  • 递归结构允许 group 嵌套 group,调度器按公平调度递归下去。

调度器如何使用它们

以cfs调度器为例,调度器在进行调度选择时:

  1. 遍历 CPU 的 rq.cfs 队列,挑选最合适的 sched_entity
  2. 如果该 sched_entity 是一个任务,就直接调度
  3. 如果该 sched_entity 是一个任务组,就进入对应的 task_group.cfs_rq[cpu]
  4. 在该队列中递归选择下一级的 sched_entity,直到选出最终的任务

为什么这么设计?

这是一种典型的 分层调度(Hierarchical Scheduling) 机制,有几个优点:

  • 支持资源公平:例如,每组任务在顶层调度中获得公平份额
  • 支持资源限制:可以对每组任务设置 CPU 份额(如通过 cfs_quota_us
  • 支持嵌套组调度:适用于容器、Kubernetes pod、服务/用户分组等
  • 实现清晰:调度逻辑复用 CFS 的实体结构和算法

task_group与 cgroup 的关系

task_group 并不是用户直接使用的接口,而是内核内部与 **cgroup**** 子系统** 的绑定结构。

# 创建一个新的 CPU 资源组
mkdir /sys/fs/cgroup/cpu/mygroup

# 向其中加入任务
echo <pid> > /sys/fs/cgroup/cpu/mygroup/tasks

当进程加入某个 cgroup 后,其 task_struct 中的 task_group 指针会指向该 cgroup 对应的 task_group 实例,调度器就会按组来对其调度。


任务分组的用途

任务分组的主要作用包括:

作用说明
资源隔离可以为每组任务限制 CPU、内存、I/O 等资源
公平调度组内共享时间片,组间公平分配 CPU
负载统计按组统计 CPU、内存使用,支持审计与性能分析
服务级别管理可按服务、容器或租户分组,管理更清晰

典型应用场景

  1. Docker 容器:每个容器会被映射为一个独立的 cgroup,自然形成任务分组。
  2. 系统级任务隔离:比如将系统服务和用户应用程序分组,防止干扰。

调试与查看

可以通过以下方式查看任务所属的 task group(cgroup):

cat /proc/<pid>/cgroup

查看调度相关的任务组结构:

cat /sys/fs/cgroup/cpu/mygroup/cpu.stat

参考资料

  1. Professional Linux Kernel Architecture,Wolfgang Mauerer
  2. Linux内核深度解析,余华兵
  3. Linux设备驱动开发详解,宋宝华
  4. linux kernel 4.12
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值