我正在学习Linux内核中多处理器系统上负载均衡器的工作原理。Linux调度器基本上使用运行队列来存储它要下一步运行的任务,现在考虑到多处理器系统,load_balancer()的实现方式如下解释:
首先,load_balance()调用find_busiest_queue()确定最繁忙的运行队列。换句话说,这是具有最多进程的运行队列。如果没有运行队列比当前队列的进程多25%或更多,则find_busiest_queue()返回NULL并且load_balance()返回。否则,将返回最繁忙的运行队列。
其次,load_balance()决定从最繁忙的运行队列中拉取哪个优先级数组。过期的数组优先,因为这些任务相对较长时间未运行,因此最可能不在处理器缓存中(也就是不是缓存热点)。如果过期的优先级数组为空,则只能选择活动数组。
接下来,load_balance()找到具有任务的最高优先级(最小值)列表,因为公平地分配高优先级任务比低优先级任务更重要。
分析给定优先级的每个任务,以查找不在运行、不通过处理器亲和力阻止迁移且不是缓存热点的任务。如果任务符合此标准,则调用pull_task()将任务从最繁忙的运行队列拉到当前运行队列中。
只要运行队列保持不平衡,就会重复前两个步骤,并从最繁忙的运行队列拉取更多任务到当前队列。最后,当不平衡得到解决时,当前运行队列被解锁并且load_balance()返回。
以下是相关代码:
我不太清楚的是上述代码中的结构体sched_domain *sd, 我查过了,这个结构体在include/linux/sched.h中定义, 链接如下http://lxr.linux.no/linux+v3.7.1/include/linux/sched.h#L895。这是一个大结构体,因此我只提供了一个链接以简化问题。 我想知道的是,在上述代码中,struct sched_domain有什么用处? 当调用load_balancer()时,为什么要使用它,这个结构体代表着什么? 以下是一些相关信息http://www.kernel.org/doc/Documentation/scheduler/sched-domains.txt, 为什么CPU需要调度域?这些域代表着什么?
首先,load_balance()调用find_busiest_queue()确定最繁忙的运行队列。换句话说,这是具有最多进程的运行队列。如果没有运行队列比当前队列的进程多25%或更多,则find_busiest_queue()返回NULL并且load_balance()返回。否则,将返回最繁忙的运行队列。
其次,load_balance()决定从最繁忙的运行队列中拉取哪个优先级数组。过期的数组优先,因为这些任务相对较长时间未运行,因此最可能不在处理器缓存中(也就是不是缓存热点)。如果过期的优先级数组为空,则只能选择活动数组。
接下来,load_balance()找到具有任务的最高优先级(最小值)列表,因为公平地分配高优先级任务比低优先级任务更重要。
分析给定优先级的每个任务,以查找不在运行、不通过处理器亲和力阻止迁移且不是缓存热点的任务。如果任务符合此标准,则调用pull_task()将任务从最繁忙的运行队列拉到当前运行队列中。
只要运行队列保持不平衡,就会重复前两个步骤,并从最繁忙的运行队列拉取更多任务到当前队列。最后,当不平衡得到解决时,当前运行队列被解锁并且load_balance()返回。
以下是相关代码:
static int load_balance(int this_cpu, runqueue_t *this_rq,
struct sched_domain *sd, enum idle_type idle)
{
struct sched_group *group;
runqueue_t *busiest;
unsigned long imbalance;
int nr_moved;
spin_lock(&this_rq->lock);
group = find_busiest_group(sd, this_cpu, &imbalance, idle);
if (!group)
goto out_balanced;
busiest = find_busiest_queue(group);
if (!busiest)
goto out_balanced;
nr_moved = 0;
if (busiest->nr_running > 1) {
double_lock_balance(this_rq, busiest);
nr_moved = move_tasks(this_rq, this_cpu, busiest,
imbalance, sd, idle);
spin_unlock(&busiest->lock);
}
spin_unlock(&this_rq->lock);
if (!nr_moved) {
sd->nr_balance_failed++;
if (unlikely(sd->nr_balance_failed > sd->cache_nice_tries+2)) {
int wake = 0;
spin_lock(&busiest->lock);
if (!busiest->active_balance) {
busiest->active_balance = 1;
busiest->push_cpu = this_cpu;
wake = 1;
}
spin_unlock(&busiest->lock);
if (wake)
wake_up_process(busiest->migration_thread);
sd->nr_balance_failed = sd->cache_nice_tries;
}
} else
sd->nr_balance_failed = 0;
sd->balance_interval = sd->min_interval;
return nr_moved;
out_balanced:
spin_unlock(&this_rq->lock);
if (sd->balance_interval < sd->max_interval)
sd->balance_interval *= 2;
return 0;
}
我不太清楚的是上述代码中的结构体sched_domain *sd, 我查过了,这个结构体在include/linux/sched.h中定义, 链接如下http://lxr.linux.no/linux+v3.7.1/include/linux/sched.h#L895。这是一个大结构体,因此我只提供了一个链接以简化问题。 我想知道的是,在上述代码中,struct sched_domain有什么用处? 当调用load_balancer()时,为什么要使用它,这个结构体代表着什么? 以下是一些相关信息http://www.kernel.org/doc/Documentation/scheduler/sched-domains.txt, 为什么CPU需要调度域?这些域代表着什么?