跨核负载均衡的关键工作流程
跨核负载均衡的关键函数如下:
-
rebalance_domains():负载均衡的触发函数。
-
load_balance():负载均衡的主函数,负责平衡各核心负载。
-
find_busiest_group():找到负载最高的调度组。
-
find_busiest_queue():在调度组中找到负载最高的队列。
-
can_migrate_task():检查任务是否可迁移。
-
move_queued_task():执行任务的实际迁移。
-
update_sg_lb_stats():收集负载均衡的统计信息。
-
attach_entity_load_avg() / detach_entity_load_avg():更新任务迁移的负载数据。
这些函数在 PELT(负载追踪)的支持下,通过实时更新和统计各个CPU核心上的负载,使 CFS 调度器能够有效地实现多核系统中的跨核负载均衡。
跨核负载均衡的定时器任务
在Linux内核中,跨核负载均衡的定时器任务实际上是通过一个周期性触发的调度软中断(softirq)机制来实现的。具体来说,跨核负载均衡的触发是由调度器周期性 tick 定时器(也称为 sched_tick)驱动的,而 rebalance_domains() 函数通常是在这个定时器触发的上下文中被调用。
- scheduler_tick() 函数
调度器的周期性 tick 定时器是由 scheduler_tick() 函数触发的,它负责周期性地为各个 CPU 核心运行负载均衡操作。
作用:scheduler_tick() 在每个时间片结束时触发,会调用与负载均衡相关的函数来判断是否需要重新平衡负载。
- 调用 rebalance_domains() 的流程
scheduler_tick() 函数并不会直接调用 rebalance_domains()。而是通过 run_rebalance_domains() 函数来间接完成负载均衡。
具体流程:
scheduler_tick() → trigger_load_balance() → run_rebalance_domains()
其中,trigger_load_balance() 会检查当前 CPU 是否需要负载均衡,并在必要时触发 run_rebalance_domains() 执行。
- run_rebalance_domains() 函数
作用:这个函数负责实际调用 rebalance_domains() 来完成跨核负载均衡。
执行逻辑:run_rebalance_domains() 会遍历所有的 sched_domain(调度域),并对每个调度域调用 rebalance_domains() 函数来进行跨核负载均衡。
- 定时任务的注册:在sched_tick()中
设计与实现
为了实现基于PELT的跨核负载均衡,除了关键函数的实现外,注意有:
- 调度域
- 调度组
- SmpCpuManager 下 active_cpus
- CpuIdleType 枚举类型
- per-CPU 变量 load_balance_mask
- 在 sched_init() 中注册软中断方法,用于触发负载均衡的 run_rebalance_domains()