《奔跑吧linux內核》3.3筆記,不足之處還望大家批評指正
根據實際物理屬性,CPU域分類如圖1所示。
圖1 CPU域分類
問題一:一個4核處理器中的每個物理CPU擁有獨立L1 cache且不支持超線程技術,分成兩個簇cluster0和cluster1,每個簇包含兩個物理CPU核,簇中的CPU核共享L2cache。請畫出該處理器在Linux內核里調度域和調度組的拓撲關系圖。
4核處理器關系圖如圖2所示,在不支持超線程技術的情況下,每個CPU核心只有一個執行線程,所以4核處理器沒有SMT屬性。cluster由兩個CPU物理核組成,這兩個CPU是MC層級且是兄弟關系。整個處理器可以看作DIE級別,因此該處理器只有兩個層級,即MC和DIE。根據上述原則,畫圖圖3所示上述4核處理器的調度域和調度組的拓撲關系圖。
圖2 4核處理器示意圖
圖3 4核處理器調度域和調度組的拓撲關系圖
問題二:假設CPU0和CPU1同屬於一個調度域中且它們都不是idle CPU,那么CPU1可以做負載均衡嗎?
CPU1不可以做負載均衡,默認約定優先由調度域中第一個CPU做負載均衡。此時,只有CPU0能做負載均衡,或者當CPU0不是空閑CPU,CPU1處於idle狀態,CPU1才可以做負載均衡。
問題三:如何查找出一個調度域里最繁忙的調度組?
在find_busiest_group()函數中,簡單歸納步驟如下:
1)首先遍歷該調度域中每個調度組,計算各個調度組中的平均負載等相關信息;
2)根據平均負載,找出最繁忙的調度組;
3)獲取本地調度組的平均負載(avg_load)和最繁忙調度組的平均負載,以及該調度域的平均負載;
4)本地調度組的平均負載大於最繁忙組的平均負載,或者本地調度組的平均負載大於調度域的平均負載,說明不適合做負載均衡,退出此次負載均衡處理;
5)根據最繁忙組的平均負載、調度域的平均負載和本地調度組的平均負載來計算該調度域的需要遷移的負載不均衡值。
問題四:如果一個調度域負載不平衡,請問如何計算需要遷移多少負載量呢?
計算方式如圖4所示。當最繁忙的調度組合本地調度組都出現group_overloaded的情況下才會計算load_above_capacity,busiest.gcf指最繁忙調度組里的group_capacity_factor。公式查看最繁忙調度組的平均負載(組里每個CPU的平均負載,不是組的總負載)和本地調度組的平均負載,以及整個調度域的平均負載的差值來計算該調度域的負載不均衡值(env->imbalance)。最后如果計算出來的不均衡值比最繁忙域里的每個進程平均負載小,那么調用fix_small_imbalance()函數,該函數計算最小的不均衡值。(SCHED_CAPACITY_SCALE為1024)
圖4 需要遷移的負載量的計算方式
問題五:使用內核提供的喚醒進程API,比如wake_up_process()來喚醒一個進程,那么進程喚醒后應該在哪個CPU上運行呢?是調用wake_up_process()的那個CPU,還是該進程之前運行的那個CPU,或者其他CPU呢?
喚醒CPU記作wakeup CPU,上次運行的CPU稱為prev CPU。
如果設置了SD_BALANCE_WAKE,在select_idle_sibling()函數中,優先選擇idle CPU。如果沒有idle CPU,就只能選擇wakeup CPU和prev CPU。當找到一個具有親和性的調度域且wakeup CPU和prev CPU不是一個CPU,wake_affine()函數會重新計算wakeup CPU和prev CPU的負載情況,如果wakeup CPU的負載加上被喚醒進程的負載比prev CPU小,那么wakeup CPU可以喚醒進程,否則選擇prev CPU。
對於沒有設置SD_BALANCE_WAKE的情況,變量sd指系統調度域中和sd_flag有相同標志位的調度域,然后開始向下遍歷查找最悠閑的調度組和最悠閑的CPU喚醒進程。