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.4.1 带宽控制 - 数据结构

如果需要开启CFS的带宽控制功能,编译内核时需要设置 CONFIG_CFS_BANDWIDTH=y, 用于CFS带宽控制的数据结构为:

/* file: kernel/sched/sched.h */
struct cfs_bandwidth {
#ifdef CONFIG_CFS_BANDWIDTH
    raw_spinlock_t lock;
    /* 一个周期的时长 */
    ktime_t period;
    /* 一个周期内的时间限额 */
    u64 quota;
    /* 本周期内剩下的可用时间 */
    u64 runtime;
    s64 hierarchical_quota;

    u8 idle;
    u8 period_active;
    u8 slack_started;
    /* 高精度定时器,每个period内定时更新runtime */
    struct hrtimer period_timer;
    /* 回收时间的定时器 */
    struct hrtimer slack_timer;
    /* 所有throttled的cfs_rq挂到该链表上,在定时器的回调函数中遍历该链表执行unthrottle操作
     */
    struct list_head throttled_cfs_rq;

    /* Statistics: */
    int nr_periods;
    int nr_throttled;
    u64 throttled_time;
#endif
};

与带宽控制相关的所有信息都封装在该结构中,系统主要通过两个量来对带宽进行控制:

  • period: 代表一个周期,带宽控制以周期为单位展开

  • quota: 一个周期内的时间限额

带宽控制是以任务组为单位进行的,因此我们可以在任务组的结构体中看到如下字段:

/* file: kernel/sched/sched.h */
struct task_group {
    /* 该任务组的带宽控制字段 */
    struct cfs_bandwidth cfs_bandwidth;
};

实际的带宽控制将会下沉到任务组的各个cfsrq中去落实,因此cfsrq也包含了与带宽控制相关的字段:

/* file: kernel/sched/sched.h */
struct cfs_rq {
#ifdef CONFIG_FAIR_GROUP_SCHED
    struct rq *rq; /* CPU runqueue to which this cfs_rq is attached */

    /* 该 cfs_rq 所属的任务组 */
    struct task_group *tg; /* group that "owns" this runqueue */

    /* 用于带宽控制的字段 */
#ifdef CONFIG_CFS_BANDWIDTH
    /* 是否开启带宽限制 */
    int runtime_enabled;
    /* 当前cfs_rq从task_group中分配到的时间配额的剩余量,如果该时间小于等于0,
     * 则需要重新从task_group中申请时间 */
    s64 runtime_remaining;

    /* 记录cfs_rq被throttle时的时间点,用于统计被throttle的时间 */
    u64 throttled_clock;
    u64 throttled_clock_task;
    u64 throttled_clock_task_time;
    /* 标记当前 cfs_rq 是否被 throttle */
    int throttled;
    /* 记录当前cfs_rq被throttle的次数,如果上层task_group被throttle时,该数字也会增加
     */
    int throttle_count;
    /* 被throttle时挂入cfs_bandwidth->throttled_cfs_rq链表 */
    struct list_head throttled_list;
#endif /* CONFIG_CFS_BANDWIDTH */
#endif /* CONFIG_FAIR_GROUP_SCHED */
};

这里主要的字段是 runtime_enabled 与 runtime_remaining, 调度器主要通过这两个字段来控制cfsrq的带宽,我们在下一节将详细讨论实现细节。

Previous2.6.4 带宽控制Next2.6.4.2 带宽控制 - 带宽时间

Last updated 3 years ago

Was this helpful?