1. 程式人生 > >【轉載】linux內核調度算法(3)--多核系統的負載均衡

【轉載】linux內核調度算法(3)--多核系統的負載均衡

調度 -- 頻繁 target tel 內核調度 intel 當前 .cn

多核CPU現在很常見,那麽問題來了,一個程序在運行時,只在一個CPU核上運行?還是交替在多個CPU核上運行呢?LINUX內核是如何在多核間調度進程的呢?又是內核又是CPU核,兩個核有點繞,下面稱CPU處理器來代替CPU核。

實際上,如果你沒有對你的進程做過特殊處理的話,LINUX內核是有可能把它放到多個CPU處理器上運行的,這是內核的負載均衡。上文說過,每個處理器上有一個runqueue隊列,表示這顆處理器上處於run狀態的進程鏈表,在多處理器的內核中,就會有多個runqueue,而如果他們的大小很不均衡,就會觸發內核的load_balance函數。這個函數會把某個CPU處理器上過多的進程移到runqueue元素相對少的CPU處理器上。

舉個例子來簡單說明這個過程吧。當我們剛fork出一個子進程時,子進程也還在當前CPU處理器的runqueue裏,它與父進程均分父進程的時間片。當然,時間片與多處理器間的負載均衡沒有關系。假設我們的系統是雙核的,父進程運行在cpu0上,那麽這個fork出來的進程也是在cpu0的runqueue中。

那麽,什麽時候會發生負載均衡呢?

1、當cpu1上的runqueue裏一個可運行進程都沒有的時候。這點很好理解,cpu1無事可作了,這時在cpu1上會調用load_balance,發現在cpu0上還有許多進程等待運行,那麽它會從cpu0上的可運行進程裏找到優先級最高的進程,拿到自己的runqueue裏開始執行。

2、第1種情形不適用於運行隊列一直不為空的情況。例如,cpu0上一直有10個可運行進程,cpu1上一直有1個可運行進程,顯然,cpu0上的進程們得到了不公平的對待,它們拿到cpu的時間要小得多,第1種情形下的load_balance也一直不會調用。所以,實際上,每經過一個時鐘節拍,內核會調用scheduler_tick函數,而這個函數會做許多事,例如減少當前正在執行的進程的時間片,在函數結尾處則會調用rebalance_tick函數。rebalance_tick函數決定以什麽樣的頻率執行負載均衡。



當idle標誌位是SCHED_IDLE時,表示當前CPU處理器空閑,就會以很高的頻繁來調用load_balance(1、2個時鐘節拍),反之表示當前CPU並不空閑,會以很低的頻繁調用load_balance(10-100ms)。預科具體的數值要看上面的interval了。

當然,多核CPU也有許多種,例如INTEL的超線程技術,而LINUX內核對一個INTEL超線程CPU會看成多個不同的CPU處理器。

上面說過,如果你沒有對你的進程做過特殊處理的話,LINUX內核是有可能把它放到多個CPU處理器上運行的,但是,有時我們如果希望我們的進程一直運行在某個CPU處理器上,可以做到嗎?內核提供了這樣的系統調用。系統調用sched_getaffinity會返回當前進程使用的cpu掩碼,而sched_setaffinity則可以設定該進程只能在哪幾顆cpu處理器上執行。當我們對某些進程有強烈的期待,或者想自己來考慮CPU間的負載均衡,可以這麽試試哈。

【轉載】linux內核調度算法(3)--多核系統的負載均衡