linux kernel 负载均衡总结
2015-10-13 09:59
1356 查看
Linux操作系统支持SMP,并且同时会运行多个进程,这些进程是如何在多个CPU之间调度的,如何进行负载均衡?
进程在如下时机决定在哪个CPU运行
1.进程被唤醒的时候,比如进程收到网络数据包,或者完成磁盘IO操作
2.进程刚被fork出来
Linux通过select_task_rq函数决定进程在哪一个CPU上进行运行。该函数在./kernel/sched/core.c中实现。
int select_task_rq(struct task_struct *p, int cpu, int sd_flags, int wake_flags)
select_task_rq的调用时机:
wake_up_new_task: 进程刚被fork出来
try_to_wake_up:进程被唤醒的时候
select_task_rq函数在决定进程在哪个CPU上运行会考虑哪些因素?
static int select_task_rq_fair(struct task_struct *p, int prev_cpu, int sd_flag, int wake_flags)
{
int cpu = smp_processor_id();
for_each_domain(cpu, tmp) {
if (!(tmp->flags & SD_LOAD_BALANCE))
break; //如果调度域不支持SD_LOAD_BALANCE,直接退出。
/*
* If both cpu and prev_cpu are part of this domain,
* cpu is a valid SD_WAKE_AFFINE target.
*/
if (want_affine && (tmp->flags & SD_WAKE_AFFINE) &&
cpumask_test_cpu(prev_cpu, sched_domain_span(tmp))) {
affine_sd = tmp;
break;
} //找到prev_cpu和cpu共同所在的最近的调度域
if (tmp->flags & sd_flag)
sd = tmp; //根据sd_flag找到满足sd_flag最大对应的调度域
else if (!want_affine)
break;
}
if (affine_sd) { //如果找到affine_sd,则使用当前cpu作为调度的CPU
sd = NULL; /* Prefer wake_affine over balance flags */
if (cpu != prev_cpu && wake_affine(affine_sd, p, sync))
new_cpu = cpu;
}
if (!sd) { //如果找不到满足sd_flags的调度域,则找附近的空闲CPU。
if (sd_flag & SD_BALANCE_WAKE) /* XXX always ? */
new_cpu = select_idle_sibling(p, new_cpu);
} else while (sd) {
struct sched_group *group;
int weight;
if (!(sd->flags & sd_flag)) {
sd = sd->child;
continue;
}
//然后找sd中负载最小的cpu作为调度cpu
new_cpu = find_idlest_cpu(group, p, cpu);
}
}
wake_flags参数的含义:
/*
* wake flags
*/
#define WF_SYNC 0x01 /* waker goes to sleep after wakeup */
#define WF_FORK 0x02 /* child wakeup after fork */
#define WF_MIGRATED 0x4 /* internal use, task got migrated */
sd_flag的含义:
#define SD_LOAD_BALANCE 0x0001/* Do load balancing on this domain. */
#define SD_BALANCE_NEWIDLE 0x0002/* Balance when about to become idle */
#define SD_BALANCE_EXEC 0x0004/* Balance on exec */
#define SD_BALANCE_FORK 0x0008/* Balance on fork, clone */
#define SD_BALANCE_WAKE 0x0010 /* Balance on wakeup */
#define SD_WAKE_AFFINE 0x0020/* Wake task to waking CPU */
#define SD_PREFER_LOCAL 0x0040 /* Prefer to keep tasks local to this domain */
#define SD_SHARE_CPUPOWER 0x0080/* Domain members share cpu power */
#define SD_POWERSAVINGS_BALANCE 0x0100/* Balance for power savings */
#define SD_SHARE_PKG_RESOURCES 0x0200/* Domain members share cpu pkg resources */
#define SD_SERIALIZE 0x0400/* Only a single load balancing instance */
#define SD_ASYM_PACKING 0x0800 /* Place busy groups earlier in the domain */
#define SD_PREFER_SIBLING 0x1000/* Prefer to place tasks in a sibling domain */
SD_LOAD_BALANCE的含义:如果对应的调度域支持SD_LOAD_BALANCE,则进行重新选择运行队列。
SD_SHARE_PKG_RESOURCES:select_idle_sibling在判断空闲core的时候,是否查找所在doman的其他cpu是否空闲。
select_task_rq_fair需要gdb调试一下,看看domain的组织结构,查找空闲cpu的时候什么时间停止?
除了进程在唤醒或者刚fork完成,还有哪些机制会导致进程运行在哪个CPU上?
如果进程只有有唤醒的时候决定在哪个CPU上,难免会导致CPU负荷不均,仅此有必要进行负载均衡。
负载均衡的调用时机:
1.周期性的调用,保证负载均衡
open_softirq(SCHED_SOFTIRQ, run_rebalance_domains);
trigger_load_balance<-scheduler_tick<-周期性的时钟中断。
在每一个CPU上通过周期性的定时中断进行触发调用。
负载均衡有两种,一种是在CPU空闲触发,一种是CPU忙时触发。
rq->idle_balance = idle_cpu(cpu);
trigger_load_balance(rq);
作为参数传递给负载均衡函数。
static void rebalance_domains(struct rq *rq, enum cpu_idle_type idle)
进程在如下时机决定在哪个CPU运行
1.进程被唤醒的时候,比如进程收到网络数据包,或者完成磁盘IO操作
2.进程刚被fork出来
Linux通过select_task_rq函数决定进程在哪一个CPU上进行运行。该函数在./kernel/sched/core.c中实现。
int select_task_rq(struct task_struct *p, int cpu, int sd_flags, int wake_flags)
select_task_rq的调用时机:
wake_up_new_task: 进程刚被fork出来
try_to_wake_up:进程被唤醒的时候
select_task_rq函数在决定进程在哪个CPU上运行会考虑哪些因素?
static int select_task_rq_fair(struct task_struct *p, int prev_cpu, int sd_flag, int wake_flags)
{
int cpu = smp_processor_id();
for_each_domain(cpu, tmp) {
if (!(tmp->flags & SD_LOAD_BALANCE))
break; //如果调度域不支持SD_LOAD_BALANCE,直接退出。
/*
* If both cpu and prev_cpu are part of this domain,
* cpu is a valid SD_WAKE_AFFINE target.
*/
if (want_affine && (tmp->flags & SD_WAKE_AFFINE) &&
cpumask_test_cpu(prev_cpu, sched_domain_span(tmp))) {
affine_sd = tmp;
break;
} //找到prev_cpu和cpu共同所在的最近的调度域
if (tmp->flags & sd_flag)
sd = tmp; //根据sd_flag找到满足sd_flag最大对应的调度域
else if (!want_affine)
break;
}
if (affine_sd) { //如果找到affine_sd,则使用当前cpu作为调度的CPU
sd = NULL; /* Prefer wake_affine over balance flags */
if (cpu != prev_cpu && wake_affine(affine_sd, p, sync))
new_cpu = cpu;
}
if (!sd) { //如果找不到满足sd_flags的调度域,则找附近的空闲CPU。
if (sd_flag & SD_BALANCE_WAKE) /* XXX always ? */
new_cpu = select_idle_sibling(p, new_cpu);
} else while (sd) {
struct sched_group *group;
int weight;
if (!(sd->flags & sd_flag)) {
sd = sd->child;
continue;
}
//然后找sd中负载最小的cpu作为调度cpu
new_cpu = find_idlest_cpu(group, p, cpu);
}
}
wake_flags参数的含义:
/*
* wake flags
*/
#define WF_SYNC 0x01 /* waker goes to sleep after wakeup */
#define WF_FORK 0x02 /* child wakeup after fork */
#define WF_MIGRATED 0x4 /* internal use, task got migrated */
sd_flag的含义:
#define SD_LOAD_BALANCE 0x0001/* Do load balancing on this domain. */
#define SD_BALANCE_NEWIDLE 0x0002/* Balance when about to become idle */
#define SD_BALANCE_EXEC 0x0004/* Balance on exec */
#define SD_BALANCE_FORK 0x0008/* Balance on fork, clone */
#define SD_BALANCE_WAKE 0x0010 /* Balance on wakeup */
#define SD_WAKE_AFFINE 0x0020/* Wake task to waking CPU */
#define SD_PREFER_LOCAL 0x0040 /* Prefer to keep tasks local to this domain */
#define SD_SHARE_CPUPOWER 0x0080/* Domain members share cpu power */
#define SD_POWERSAVINGS_BALANCE 0x0100/* Balance for power savings */
#define SD_SHARE_PKG_RESOURCES 0x0200/* Domain members share cpu pkg resources */
#define SD_SERIALIZE 0x0400/* Only a single load balancing instance */
#define SD_ASYM_PACKING 0x0800 /* Place busy groups earlier in the domain */
#define SD_PREFER_SIBLING 0x1000/* Prefer to place tasks in a sibling domain */
SD_LOAD_BALANCE的含义:如果对应的调度域支持SD_LOAD_BALANCE,则进行重新选择运行队列。
SD_SHARE_PKG_RESOURCES:select_idle_sibling在判断空闲core的时候,是否查找所在doman的其他cpu是否空闲。
select_task_rq_fair需要gdb调试一下,看看domain的组织结构,查找空闲cpu的时候什么时间停止?
除了进程在唤醒或者刚fork完成,还有哪些机制会导致进程运行在哪个CPU上?
如果进程只有有唤醒的时候决定在哪个CPU上,难免会导致CPU负荷不均,仅此有必要进行负载均衡。
负载均衡的调用时机:
1.周期性的调用,保证负载均衡
open_softirq(SCHED_SOFTIRQ, run_rebalance_domains);
trigger_load_balance<-scheduler_tick<-周期性的时钟中断。
在每一个CPU上通过周期性的定时中断进行触发调用。
负载均衡有两种,一种是在CPU空闲触发,一种是CPU忙时触发。
rq->idle_balance = idle_cpu(cpu);
trigger_load_balance(rq);
作为参数传递给负载均衡函数。
static void rebalance_domains(struct rq *rq, enum cpu_idle_type idle)
相关文章推荐
- linux下svnsyncs版本库的同步更新
- CentOS6.5搭建LNMP
- CentOS6.5搭建LNMP
- Linux下配置IP及安装vmware tool
- linux 命令总结
- linux 安装opencv
- Linux 命令 - killall: 通过进程名向进程发送信号
- Linux学习记录(15)SELinux基础知识
- Linux系统下运行jar文件,提示:No main manifest attribute, in XXX.jar
- 需求:在openstack中安装极小的Linux,可以安装Firefox浏览器,接着安装selenium完成自动化网页测试
- linux 查看磁盘空间大小
- 删CentOS / RHEL库和配置文件(Repositories and configuraiton files)
- linux v4L2 初步框架
- 《王保明老师----Linux开发学习笔记》------讲03:进程 -----fork( )函数的一点理解
- Linux 查看网卡流量iptraf
- [国嵌笔记][006][Linux文本编辑器]
- Linux抓包
- 学习日志---linux打卡8
- Linux抓包
- Linux抓包