【内核调度、负载计算】【update_load_avg】

update_load_avg

/* Update task and its cfs_rq load average */
static inline void update_load_avg(struct sched_entity *se, int flags)
{
	struct cfs_rq *cfs_rq = cfs_rq_of(se);//se中的cfs_rq字段
	u64 now = cfs_rq_clock_task(cfs_rq);
	struct rq *rq = rq_of(cfs_rq);
	int cpu = cpu_of(rq);
	int decayed;

	/*
	 * Track task load average for carrying it to new CPU after migrated, and
	 * track group sched_entity load average for task_h_load calc in migration
	 */
	if (se->avg.last_update_time && !(flags & SKIP_AGE_LOAD))
		__update_load_avg_se(now, cpu, cfs_rq, se);

	decayed  = update_cfs_rq_load_avg(now, cfs_rq);
	decayed |= propagate_entity_load_avg(se);

	if (decayed && (flags & UPDATE_TG))
		update_tg_load_avg(cfs_rq, 0);
}

__update_load_avg_se

更新entity的load avg,核心是调用到了  ___update_load_avg函数

static int
__update_load_avg_se(u64 now, int cpu, struct cfs_rq *cfs_rq, struct sched_entity *se)
{
	if (___update_load_avg(now, cpu, &se->avg,
			       se->on_rq * scale_load_down(se->load.weight),
			       cfs_rq->curr == se, NULL, 0, 0)) {
		trace_sched_load_se(se);
		cfs_se_util_change(&se->avg);

#ifdef UTIL_EST_DEBUG
		/*
		 * Trace utilization only for actual tasks.
		 *
		 * These trace events are mostly useful to get easier to
		 * read plots for the estimated utilization, where we can
		 * compare it with the actual grow/decrease of the original
		 * PELT signal.
		 * Let's keep them disabled by default in "production kernels".
		 */
		if (entity_is_task(se)) {
			struct task_struct *tsk = task_of(se);

			trace_sched_util_est_task(tsk, &se->avg);

			/* Trace utilization only for top le
<think>嗯,用户问的是Linux中的runnable_avg,我需要先回忆一下相关的知识。首先,runnable_avg是Linux调度器中的一个指标,用于评估CPU的负载情况。记得它和进程的调度有关,可能涉及到CFS(完全公平调度器)的部分。 然后,我得确认runnable_avg具体的作用是什么。应该是用来跟踪可运行进程的平均数量,帮助调度器判断CPU的繁忙程度。这样系统可以根据负载情况做出更合理的调度决策,比如唤醒空闲的CPU或者进行负载均衡。 接下来,用户可能需要了解它的实现机制。这里可能需要提到指数移动平均(EMA),因为Linux常用这种方法来平滑数据,避免突变带来的影响。具体来说,runnable_avg可能会计算最近一段时间内的可运行进程数,通过衰减系数来加权新旧数据,得到平滑的平均值。 还要考虑到时间常数的概念,比如半衰期,这决定了历史数据的影响衰减速度。半衰期越长,历史数据的影响越大,反之则更关注近期数据。Linux中可能有不同的时间常数设置,用于不同的场景,比如负载的快速变化和长期趋势的平衡。 另外,runnable_avg和其他指标的关系也需要解释清楚,比如和load average的区别。虽然两者都反映系统负载,但runnable_avg更专注于可运行状态的任务,而load average包括不可中断状态的任务。这可能影响系统对负载的判断和处理方式。 用户可能还关心实际应用中的意义,比如如何影响进程迁移、CPU频率调整等。例如,当runnable_avg较高时,调度器可能会将进程迁移到其他CPU,或者提升CPU频率以处理更多任务。 最后,需要检查是否有遗漏的重要细节,比如相关的内核代码位置,或者具体的计算公式。可能需要提到结构体中的字段,比如struct sched_avg中的runnable_avg,以及如何在内核中更新这些值。 总结起来,回答需要从概念、实现原理、计算方法、与其他指标的区别以及实际应用等方面展开,确保结构清晰,逐步深入,帮助用户全面理解runnable_avg的作用和机制。</think>以下是对Linux内核中`runnable_avg`的逐步解析: ### 1. 基本概念 `runnable_avg`是Linux CFS调度器中用于量化**CPU负载**的关键指标,它表示在特定时间窗口内处于**可运行状态(Runnable)任务的平均数量**。这里的“可运行状态”指任务已准备好执行,但因CPU资源竞争而等待调度的状态。 ### 2. 核心作用 $$ \text{runnable_avg} = \text{对可运行任务数量的指数衰减移动平均} $$ - **调度决策**:帮助调度器识别CPU是否过载 - **负载均衡**:指导任务在多个CPU核心间迁移 - **频率调节**:为CPU DVFS(动态电压频率调整)提供依据 ### 3. 实现原理 #### 3.1 时间窗口计算 使用**指数衰减移动平均(EMA)**算法: $$ \text{load} = \text{load} \times y + \text{active} \times (1 - y) $$ 其中: - $y = e^{-1/(\tau \cdot 1024)}$ 是衰减因子 - $\tau$ 是时间常数(默认32ms) - `active`表示当前可运行任务数 #### 3.2 数据结构 内核中通过`struct sched_avg`实现: ```c struct sched_avg { u64 last_update_time; unsigned long load_sum; unsigned long runnable_sum; unsigned long util_sum; u32 period_contrib; unsigned long load_avg; unsigned long runnable_avg; // ← 核心字段 unsigned long util_avg; }; ``` ### 4. 更新机制 - **触发时机**: - 任务唤醒(`enqueue_task`) - 任务休眠(`dequeue_task`) - 定时器中断(`scheduler_tick`) - **计算过程**: 1. 计算自上次更新后的时间差$\Delta t$ 2. 根据时间差计算衰减系数 3. 更新`runnable_sum`和`runnable_avg` ### 5. 与Load Average的区别 | 指标 | 包含状态 | 时间范围 | 用途 | |-----------------|-------------------|------------|----------------------| | `runnable_avg` | 仅Runnable状态 | 短期(ms级) | 实时调度决策 | | Load Average | Runnable+Uninterruptible | 长期(1/5/15分钟) | 系统负载监控 | ### 6. 实际应用示例 当CPU的`runnable_avg`超过某个阈值时: 1. 调度器认为该CPU过载 2. 触发负载均衡机制 3. 将部分任务迁移到空闲CPU 4. 可能提升目标CPU的频率(通过CPUFreq框架) ### 7. 性能影响 - **精度权衡**:较短的时间常数能更快响应负载变化,但会增加计算开销 - **默认配置**:通过`CONFIG_SCHED_DEBUG`可调整时间常数`sysctl_sched_time_avg` ### 8. 监控方法 ```bash # Per-CPU runnable任务数 cat /proc/sched_debug | grep "runnable" # 整体系统负载 mpstat -P ALL 1 ``` 该机制自Linux 3.8引入,经过多次优化(如PELT算法改进),是理解现代Linux调度行为的关键组件。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值