前言:標題談的是多核CPU下綁定某個中斷到指定的CPU的方法,但是實際工作中,這個方法可以適配很多種數據接收的情況,所以就記錄一下自己之前工作上遇到的具體某一個問題以及解決方法。
之前有一個項目,需要串口接收大量的數據,硬件平台采用的是NXP的I.MX6D系列芯片,雙核CPU。實際發現,在接收數據的時候,總是出現數據接收不及時的情況,分析了一下官方提供的Linux內核代碼,默認使用的是串口中斷的方式接收。產品運行的時候,1ms會上傳64字節的數據到I.MX6的串口,也就是說單位時間內串口的中斷量非常的大,將Linux系統的節拍提升到1000Hz也沒有改善情況。實際上我在兩小時內大約統計到了億次級別的中斷量。調試過程中,在板級文件中配置串口使用DMA功能,發現3.0.35版本的內核DMA功能是有問題的,實際數據接收的效果會出現很明顯的數據丟失情況,效果還不如直接用串口中斷接收的好。所以問題就在於怎樣才能讓中斷接收更及時(PS:在剛開始分析這個問題的時候,我甚至懷疑是tty讀取數據的速度跟不上uart中斷接收數據造成的,然后去改動NXP官方的驅動,雖然數據接收有改善的現象,但是實際問題並沒有得到解決)。
頻繁的產生硬件中斷,是一件非常消耗CPU的事情,但是實際上並沒有出現CPU以及系統跑不動的現象,但是系統能跑動並不代表着中斷就能及時響應,因為Linux系統不是實時的操作系統。通過top命令查看,系統運行情況一切都正常。后來一想,雙核CPU,我是不是兩顆CPU都真正使用到了呢?會不會出現雖然是雙核CPU,但是只跑單核的情況?帶着這個問題,我查看了一下系統的中斷分配情況(PS:為什么不是top命令來查看呢?我解釋一下,當時使用top命令,確實是發現兩顆CPU都是有4%左右的使用率,而且也在實時變動,干擾了我的判斷,所以看底層最直接),具體的命令是#cat /proc/interrupts,這個命令會列出當前系統存在的中斷,以及該中斷是在哪一顆CPU上。運行命令后我發現,雖然是雙核CPU,但是所有的中斷(包括串口、SPI、I2C、SDMA、Timer等)都集中在了CPU0,也就是說實際上CPU1啥事兒都沒干,CPU0在忙着中斷接收數據,CPU1在一旁圍觀。這種情況,我不知道是官方提供的Linux內核對多核CPU適配不夠好,還是需要實際使用者自己安裝第三方工具來管理CPU中斷資源的分配。
運行# /etc/init.d/irqbalance stop 發現我們產品的根文件系統根本沒有這個工具,因此初步分析是我們自己做的根文件系統沒有安裝SMP負載均衡相關的管理工具導致的所有中斷都集中在CPU0來處理的情況。所以針對實際使用出現數據接收不及時以及丟包的情況,我將串口接收數據的中斷綁定到了空閑的CPU1(其他跟數據接收不緊要的中斷保持在CPU0來響應),具體命令是:# echo "2" > /proc/irq/62/smp_affinity,62這個數字就是串口的中斷號。運行前面的命令之后,再次#cat /proc/interrupts,發現該串口中斷已經成功指定在CPU1來執行,實際數據接收不及時的問題得到解決。
總結:中斷響應不及時這樣的問題,影響因素有很多,比如系統本身就不是實時性的,存在很多的系統調度。再者I.MX6平台的串口使用中斷接收數據,在中斷的上半部將數據push到tty中,實際上tty是使用工作隊列來接收數據的(tty注冊了工作隊列),難免會有調度上的不及時。而串口開啟了DMA的話,也是在驅動probe階段初始化了一個工作隊列,將數據接收的工作放到了中斷下半部來執行,進而push數據到tty(又有一個工作隊列),相當於是如果使用DMA的話,數據接收流程就有了兩個工作隊列,也就造成了使用DMA的效果比串口中斷接收還要更差(目前是我自己的理論分析,如果有錯還請大家指出,謝謝)。同時中斷處理函數還頻繁使用了自旋鎖,這也會導致中斷響應變慢的情況,今后做系統優化,可以往這方面考慮。