Linux核心概念详解
  • 0. Linux核心概念详解
  • 1. 调试环境
  • 2. Linux 调度器
    • 2.1 任务
    • 2.2 核心概念
      • 2.2.1 核心概念 - 调度实体
      • 2.2.2 核心概念 - 调度类
      • 2.2.3 核心概念 - 调度策略
      • 2.2.4 核心概念 - 运行队列
      • 2.2.5 核心概念 - 优先级
    • 2.3 演进历史
      • 2.3.1 O(n)调度器 - 调度逻辑
      • 2.3.2 O(n)调度器 - 时间分配
      • 2.3.3 O(n)调度器 - 调度时机
      • 2.3.4 O(1)调度器 - 简介
      • 2.3.5 O(1)调度器 - 调度逻辑
      • 2.3.6 O(1)调度器 - 时间分配
      • 2.3.7 RSDL
      • 2.3.8 CFS
    • 2.4 DL调度器
      • 2.4.1 DL调度器 - 调度算法
      • 2.4.2 DL调度器 -核心代码
    • 2.5 RT调度器
    • 2.6 CFS
      • 2.6.1 公平性
      • 2.6.2 调度逻辑
      • 2.6.2.1 调度逻辑 - 数据结构
      • 2.6.2.2 调度逻辑 - vruntime
      • 2.6.2.3 调度逻辑 - 调度周期
      • 2.6.2.4 调度逻辑 - 调度节拍
      • 2.6.2.5 调度逻辑 - 任务抢占
      • 2.6.2.6 调度逻辑 - 调度时机
      • 2.6.3 组调度
      • 2.6.3.1 组调度 - 数据结构
      • 2.6.3.2 组调度 - 调度逻辑
      • 2.6.3.3 组调度 - 时间分配
      • 2.6.3.4 组调度 - 任务组权重
      • 2.6.4 带宽控制
      • 2.6.4.1 带宽控制 - 数据结构
      • 2.6.4.2 带宽控制 - 带宽时间
      • 2.6.4.3 带宽控制 - 挂起与解挂
      • 2.6.4.3 带宽控制 - 定时器
    • 2.7 负载追踪
      • 2.7.1 负载追踪 - 简介
      • 2.7.2 负载追踪 - 数据结构
      • 2.7.3 负载追踪 - 计算负载
      • 2.7.4 负载追踪 - 更新负载
    • 2.8 负载均衡
      • 2.8.1 简介
      • 2.8.2 CPU的拓扑结构
      • 2.8.3 数据结构
      • 2.8.4 算法思路
      • 2.8.5 触发时机
      • 2.8.6 总结
  • 3. LINUX 内存管理
    • 3.1 寻址模式
      • 3.1.1 地址
      • 3.1.2 地址转换
      • 3.1.3 Linux的地址空间
    • 3.2 物理内存
      • 3.2.1 数据结构
      • 3.2.2 初始化
      • 3.2.3 物理内存模型
      • 3.2.4 Buddy System(伙伴系统)
      • 3.2.5 SLAB/SLUB/SLOB
Powered by GitBook
On this page

Was this helpful?

  1. 2. Linux 调度器
  2. 2.6 CFS

2.6.3.3 组调度 - 时间分配

如果se代表的是任务组,那么该se在当前cfsrq中根据权重分配到的时间还需要在自己的任务组内进行二次分配。为se计算时间份额的函数是 sched_slice, 该函数的逻辑在调度周期中已经分析过,这里我们再看一下该函数对任务组的处理方式:

/* file: kernel/sched/fair.c */
static u64 sched_slice(struct cfs_rq *cfs_rq, struct sched_entity *se) {
unsigned int nr_running = cfs_rq->nr_running;
u64 slice;

/* 调度周期 */
slice = __sched_period(nr_running + !se->on_rq);

/* 处理任务组的循环,颜色se的parent一路往上爬升 */
for_each_sched_entity(se) {
struct load_weight *load;
struct load_weight lw;

cfs_rq = cfs_rq_of(se);
/* 整个运行队列 cfs_rq 的总权重 */
load = &cfs_rq->load;

/* 从时间总额slice中为se分配其应得的份额,根据se在整个队列中的权重比例进行分配 */
slice = __calc_delta(slice, se->load.weight, load);
}

if (sched_feat(BASE_SLICE))
slice = max(slice, (u64)sysctl_sched_min_granularity);

return slice;
}

#define for_each_sched_entity(se) for (; se; se = se->parent)

任务组内部对时间做二次分配的算法思路也是一样的,即根据目标 se 与任务组的总体权重比例进行分配。我们知道一个任务组的所有调度实体都在一个cfsrq中,代码通过 se->parent 一路往上走,依次计算出每个任务组中的时间配额,循环结束后即得到 se 最终的时间配额。我们通过一个示意图来理解总体流程:

图中目标的调度实体为 SE2, 其最终的时间配额结果是 slice0 = slice * r2 * r1 * r0, 其中 slice 是总时间,可以看出不管任务组嵌套多少层,目标调度实体不管处在哪一层,最终都可以正确计算出其应该分配到的时间配额。

Previous2.6.3.2 组调度 - 调度逻辑Next2.6.3.4 组调度 - 任务组权重

Last updated 3 years ago

Was this helpful?