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的带宽,我们在下一节将详细讨论实现细节。
Last updated
Was this helpful?