Linux中斷負載均衡

     Linux 內核需要對連接到計算機上的所有硬件設備進行管理,毫無疑問這是它的份內事。如果要管理這些設備,首先得和它們互相通信才行,一般有兩種方案可實現這種功能:

  1. 輪詢(polling 讓內核定期對設備的狀態進行查詢,然後做出相應的處理;
  2. 中斷(interrupt 讓硬件在需要的時候向內核發出信號(變內核主動爲硬件主動)。

    第一種方案會讓內核做不少的無用功,因爲輪詢總會週期性的重複執行,大量地耗用 CPU 時間,因此效率及其低下,所以一般都是採用第二種方案 。

 

    對於中斷,Linux也有自己的負載均衡策略,既可以調用Linux自己的優化模塊irqbalance來實現自動的優化調節,也可以人爲的將中斷進行綁定的固定的物理CPU上。

 

1、irqbalance

(1)irqbalance簡介與使用

        irqbalance用於優化中斷分配,它會自動收集系統數據以分析使用模式,並依據系統負載狀況將工作狀態置於 Performance mode 或 Power-save mode。處於Performance mode 時,irqbalance 會將中斷儘可能均勻地分發給各個 CPU core,以充分利用 CPU 多核,提升性能。處於Power-save mode 時,irqbalance 會將中斷集中分配給第一個 CPU,以保證其它空閒 CPU 的睡眠時間,降低能耗。

         irqbalance這個進程默認是開機啓用的,可以通過如下命令它的狀態

# service irqbalance status
irqbalance (pid PID) is running…

        對於人爲將中斷綁定到CPU上的情況時,爲了消除irqbalance的自適應調節,需要將該進程關閉,可以用下面的命令關閉它:

# service irqbalance stop
Stopping irqbalance: [ OK ]

或者乾脆取消開機啓動:

# chkconfig irqbalance off

(2)irqbalance原理分析

      irqbalance的意義在於SMP系統的中斷優化,而SMP架構是一種CPU的分層拓撲,如下圖所示

       一個NUMA node包括一個或者多個Socket,以及與之相連的local memory。一個多核的Socket有多個Core。如果CPU支持超線程並開啓,操作系統還會把這個Core看成 2個Logical Processor。因此irqbalance會需要考慮到各個CPU上的中斷負載以及CPU所處的拓撲位置來進行中斷優化調節。

     irqbalance的源碼下載可以到github網站https://github.com/Irqbalance

     個人對其源碼的分析在https://github.com/lkn910907/Code-analyze/tree/master/irqbalance%E4%BB%A3%E7%A0%81%E5%88%86%E6%9E%90,可便於新手瞭解。

//irqbalance.c
int main(int argc, char** argv)
{
  /* ... */
  while (keep_going) {
                sleep_approx(SLEEP_INTERVAL); //#define SLEEP_INTERVAL 10
                /* ... */
                clear_work_stats();
                parse_proc_interrupts();
                parse_proc_stat();
                /* ... */
                calculate_placement();
                activate_mappings();
                /* ... */
}
/* ... */
}

     從程序的主循環可以很清楚的看到它的邏輯,在退出之前每隔10秒它做了以下的幾個事情:
1. 清除統計
2. 分析中斷的情況
3. 分析中斷的負載情況
4. 根據負載情況計算如何平衡中斷
5. 實施中斷親和性變更

     如果不瞭解中斷親和性可以下面找到詳細說明 ~

     在診斷模型下運行irqbalance可以給我們很多詳細的信息:

#irqbalance  –debug

     可以詳細看到irqbalcne對每個CPU的拓撲分層,以及每個拓撲域上的負載。

 

(2)自己設置中斷親和性

     在 SMP 體系結構中,我們可以通過調用系統調用和一組相關的宏來設置 CPU 親和力(CPU affinity),將一個或多個進程綁定到一個或多個處理器上運行。中斷在這方面也毫不示弱,也具有相同的特性。中斷親和力是指將一個或多箇中斷源綁定到特定的 CPU 上運行。中斷親和力最初由 Ingo Molnar 設計並實現。

     在 /proc/irq 目錄中,對於已經註冊中斷處理程序的硬件設備,都會在該目錄下存在一個以該中斷號命名的目錄 IRQ#IRQ# 目錄下有一個 smp_affinity 文件(SMP 體系結構纔有該文件),它是一個 CPU 的位掩碼,可以用來設置該中斷的親和力, 默認值爲 0xffffffff,表明把中斷髮送到所有的 CPU 上去處理。如果中斷控制器不支持 IRQ affinity,不能改變此默認值,同時也不能關閉所有的 CPU 位掩碼,即不能設置成 0x0

     需要注意的是人爲設置中斷親和性需要關閉irqbalance,消除其自適應中斷調節

        

     我們以網卡(eth1,中斷號 44 )爲例,在具有 8 個 CPU 的服務器上來設置網卡中斷的親和力(以下數據出自內核源碼Documentation\IRQ-affinity.txt):

[root@moon 44]# cat smp_affinity
ffffffff
[root@moon 44]# echo 0f > smp_affinity
[root@moon 44]# cat smp_affinity
0000000f

     當我們通過 echo 命令將 CPU 掩碼寫進 smp_affinity 文件時,此時的調用路線圖爲:write() ->sys_write() ->vfs_write() ->proc_file_write() ->irq_affinity_write_proc() ->set_affinity() ->set_ioapic_affinity() ->set_ioapic_affinity_irq() ->io_apic_write();其中在調用 set_ioapic_affinity_irq() 函數時,以中斷號和 CPU 掩碼作爲參數,接着繼續調用 io_apic_write(),修改相應的中斷重定向中的值,來完成中斷親和力的設置。

     對於效果的檢驗,可以通過cat /proc/interrupts命令查看中斷在各個CPU上的分佈,如果是對特定中斷處理,再加上grep過濾更方便查看。通過可以發現,一旦設置了親和性,中斷就只在特定的CPU上觸發了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章