Chinaunix首页 | 论坛 | 博客
  • 博客访问: 38560
  • 博文数量: 6
  • 博客积分: 170
  • 博客等级: 入伍新兵
  • 技术积分: 73
  • 用 户 组: 普通用户
  • 注册时间: 2010-04-23 14:18
文章分类

全部博文(6)

文章存档

2012年(6)

分类: LINUX

2012-06-13 19:51:35

每一个CPU都有一个基本的调度域(struct sched_domain)。域间的继承关系通过这些基本域的parent指针来表示。parent必须以NULL结束,域结构必须为per-cpu,这样有利于无锁更新。
 每个调度域跨越几个cpu(存储在span域中)。一个域的span必须是其子域span的超集,同时对于cpu i的基本域而言必须至少包含cpu i。 通常来说每个cpu的顶层域跨越系统的所有cpu,尽管严格意义上说这不是必须的,但是这样的话会导致只有cpu allowed mask显式设置,否则会有一些cpu永远不会分配任务。一个调度域跨度则意味着在这些cpu之间平衡进程负载。
 
每个调度域必须有一个或多个cpu组(struct sched_group),通过groups指针组织为一个循环单链表。这些groups的cpumasks的联合必须和域的跨度相同。任意组之间的cpumasks交集必须为空。通过groups指针指向的组必须包含域拥有的cpu。组可以在cpu之间共享,因为在其初始化之后, 其为只读数据。

在一个调度域中进行均衡是在groups之间进行的。即为,每个group作为一个entity。一个组的负载定义为其组中cpu的负载之和,只有组的负载变得不均衡时才在组之间进行迁移。

在kernel/sched/sched.c中, trigger_load_balance()通过sheduler_tick()函数在每个cpu上周期性的调用。在为当前runqueue的下一次正常的调度重平衡事件来到时,其引起一个软中断。事实上的负载均衡工作,run_rebalance_domains()->rebalance_domains(),在一个软中断(SCHED_SOFTIRQ)上下文运行。

后一个函数接收两个参数, 当前cpu和在scheduler_tick()发生时其是否idle。迭代cpu所在的所有调度域。从其基本的域开始通过parent链向上迭代。在做这些事情的时候,他检查看是否当前的域用尽了他的重平衡时间段。如果是,他在那个域运行load_balance(),然后再检查其父域,。。。。

刚开始,load_balance()找到当前调度域中的最忙组。如果成功,其寻找该组中最忙cpu的runqueue。如果其成功的找到了这样一个runqueue,其锁定初始的cpu runqueue和新找到的最忙的runqueue,然后开始迁移任务到我们的runqueue。迁移任务的准确数字为在迭代sched_domain时所有的组计算的不平衡值。

实现sched_domains
基本的域跨越层次结构的第一层。在SMT中, 会跨越所有一个物理cpu的sblings, 每一个组为一个虚拟cpu。

在SMP中, 基本域的父节点将跨越改节点的所有物理cpu。每一个组是一个单独的物理cpu。在numa中,则smp父域会跨越整个系统,每个组有一个组的cpumask。

实现者必须阅读include/linux/sched.h中的注释:struct sched_domain域, SD_FLAG_*, SD_*_INIT来获得基本信息和适当的调节。

对SMT, architectures必须定义CONFIG_SCHED_SMT并提供cpumask_t cpu_sibling_map[NR_CPUS], 其中cpu_sibling_map[i]是所有i的siblings和他自己的mask。

architecture可以完全覆盖通用的域builder,通过定义 ARCH_HASH_SCHED_DOMAIN,然后导出自己的arch_init_shed_domains函数。该函数会将所有的域attach到使用的cpu_attach_domain的所有cpu中。

sched-domains debugs 可用通用CONFIG_SCHED_DEBUG打开。
阅读(1790) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~