26
2017
09

linux调度之SMP负载均衡

SMP调度背景

  在多处理器系统上,内核必须考虑好几个额外的问题,以确保良好的调度。

  • CPU负荷必须尽可能公平地在所有处理器上共享。
  • 进程与系统中某些处理器的亲合性(affinity)必须是可设置的。
  • 内核必须是能够将进程从一个CPU迁移到另一个上。

linux SMP调度就是将进程安排/迁移到合适的CPU中去,保持各CPU负载均衡的过程。如下图所示。

smp

SMP调度时机

  • scheduler_tick
  • try_to_wake_up(优先选择在唤醒的CPU上运行)
  • exec系统调用启动一个新进程时

SMP调度分析

CPU拓扑关系构建

系统启动时开始构建CPU拓扑关系。

这里写图片描述

在ARM中,4核处理器示意图如下所示:

这里写图片描述

上述4核处理器最后生成的调度域与调度组的拓扑关系图如下图如示:

这里写图片描述

load_balance

  1. 首先,load_balance()调用find_busiest_queue()来选出最忙的运行队列,在这个队列中具有最多的进程数。这个最忙的运行队列应该至少比当前的队列多出25%的进程数量。如果不存在具备这样条件的队列,find_busiest_queue()函数NULL,同时load_balance()也返回.如果存在,那么将返回这个最忙的运行时队列.

  2. 然后,load_balance()函数从这个最忙的运行时队列中选出将要进行负载平衡的优先级数组(priority array).选取优先级数组原则是,首先考虑过期数组(expired array),因为这个数组中的进程相对来说已经很长时间没有运行了,所以它们极有可能不在处理器缓冲中.如果过期数组(expired priority array)为空,那就只能选择活跃数组(active array).

  3. 下一步,load_balance()找出具有最高优先级(最小的数字)链表,因为把高优先级的进程分发出去比分发低优先级的更重要。

  4. 为了能够找出一个没有运行,可以迁移并且没有被缓冲的进程,函数将分析每一个该队列中的进程.如果有一个进程符合标准,pull_task()函数将把这个进程从最忙的运行时队列迁移到目前正在运行的队列。

  5. 只要这个运行时队列还处于不平衡的状态,函数将重复执行3和4,直到将多余进程从最忙的队列中迁移至目前正在运行的队列.最后,系统又处于平衡状态,当前运行队列解锁,load_balance()返回。

try_to_wake_up

唤醒进程涉及到应该由哪个CPU来运行唤醒进程。当找到一个亲和性的调度域且唤醒的CPU与之前该进程运行的CPU不是同一个CPU,考虑使用当前CPU来唤醒进程。也就是说优先选择wakeup CPU,否则选择pre CPU.

参考资料

<1>.《奔跑吧Linux》
<2>.《深入理解linux架构》

上一篇:Android TextView 代码中设置 drawableLeft 下一篇:unity shader:初探透明度