linux kernel 負載平衡總結__linux

來源:互聯網
上載者:User

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)







聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.