接上文,本文主要介绍load_balance的工作流程。
负载均衡很复杂,但是最终都会走到load_balance这个函数,所以理清这个函数对理解负载均衡是很有必要的。
先看一下参数部分,可以看到大部分参数先赋值给了env,因为内核都是c语言,如果一堆参数不停的被使用,那还是将其放在一个结构体中方便很多。
static int load_balance(int this_cpu, struct rq *this_rq,
struct sched_domain *sd, enum cpu_idle_type idle,
int *continue_balancing)
{
int ld_moved, cur_ld_moved, active_balance = 0;
struct sched_domain *sd_parent = sd->parent;
struct sched_group *group;
struct rq *busiest;
struct rq_flags rf;
struct cpumask *cpus = this_cpu_cpumask_var_ptr(load_balance_mask);
struct lb_env env = {
.sd = sd,
.dst_cpu = this_cpu,
.dst_rq = this_rq,
.dst_grpmask = sched_group_span(sd->groups),
.idle = idle,
.loop_break = sched_nr_migrate_break,
.cpus = cpus,
.fbq_type = all,
.tasks = LIST_HEAD_INIT(env.tasks),
};
其实通过env,load balance的逻辑基本已经有了,即找到这个 sched_domain中最忙的sched_group中的cpu,把它的任务迁移给dst cpu。
这里牵扯到了新的概念,sched_domain和sched_group
负载均衡的目的是让任务均衡的运行在cpu上,但是,如果每次负载均衡都遍历所有cpu,成本肯定会很高,同时,cpu与cpu之间的地位也不是相等的, 有的“相隔较远”,有的“相隔较近”, 进行迁移的代价是不一样的。这里一般是三个维度&