CPU亲缘性及网卡中断绑定
#####編輯器依舊那么難用 難用 難用~~################
##################################################
?
CPU親緣性及網卡中斷綁定
每個CPU的每個核心都會被識別成一個邏輯CPU,由一個核心會存在超線程的功能,所以一個物理核心會表現成為多個cpu
?
多個cpu之間是如何通信的:
首先了解幾個概念
smp: 對等的訪問內存空間,事實上cpu訪問內存是通過內存控制器的芯片進行的
numa: 非一致性內存訪問機制
?http://yijiu.blog.51cto.com
numa體系
簡單來講是每個物理cpu,非物理核心
每個socket上所插入的cpu都被稱為本地節點,而所有非本地節點,都稱為遠程節點,而距離彼此cpu比較近的節點被稱為鄰居節點
?
如果cpu相對比較多,從一個節點到另一個節點距離比較長,簡單來講每個內存都有內存控制器來控制,所以如果有4顆cpu ,每個cpu如果都本地內存,每個cpu在使用數據向所屬的本地cpu內存發起請求,同時在本地內存中獲取數據
?http://yijiu.blog.51cto.com
但是,如果沒有數據,也很可能被其他cpu占用了,所以很有可能有這樣的結果:
當一個進程被從cpu2 調到cpu0上來執行的時候,那么它的數據則在cpu2上,所以cpu0不得向自己的內存控制器發送請求,而自己的內存控制器則去聯系對方的內存控制器 ,對方的控制器再從而取得數據,從而返回數據
?htt~p:/? /yi jiu.b log.51 cto.com
所以這樣性能會下降,因此需要對cpu的使用需要關注
#每一段內存都被稱為一個節點 node
以上為numa體系,因此在numa結構中,為了保證一個進程在cpu上運行時,保證數據讀取都在本地節點上進行,那么則將進程綁定在cpu上;如果僅有一顆cpu也應該將進程綁定在cpu上,因為內部可能有多個核心,這些核心使用的數據有可能也是一段一段
?
上下文切換也是需要使用資源的對于某些執行頻率特別高的服務,比如Nginx
這里考慮的僅是多核心,如果是單核心則無所謂
?.blog.51cto.com
CPU跟外部某一設備通訊時,如何知道是否存在數據
通過三種方式:
1.輪詢?忙等待,每隔一定時間就去掃描所有已注冊的io端口
2.中斷?事實上是一個電信號,如果發生變化的時候都會通知cpu,cpu接到信號之后立即切換中斷上下文,說白了就是切換到內核模式,由內核來指揮cpu處理過程事件
因此,必須有一種方式讓cpu自我感知有事件發生,而且可以立即切換中斷上下文,讓內核馬上處理
如果多個cpu的話,意味著注冊信號使用中斷cpu時,只需中斷其中某一顆就可以了?
?
·cpu如何知道是哪個中斷發生
在cpu中,存在一個特殊的物理芯片:可中斷控制器
中斷控制器中有很多針腳,每個針腳,表示一個中斷線,簡單來講是可以引用一個中斷,但是中斷線非常有限,所以使得一個針腳來標識一個中斷導致io過多不夠使用。
事實上可以通過中斷向量來標識不同中斷的,因此每個io設備發送中斷時不再通過針腳,而是通過中斷號(中斷請求)來標識的,cpu正式通過這個標識來判斷哪個發生中斷,接下來通知內核,由內核來控制cpu進行切換中斷上下文
?
·中斷通常必須立即切換
中斷分為上半部和下半部,一旦中斷發送,內核被喚醒之后立即著手分配一個能夠找到此中斷請求的中斷處理程序來嘗試處理中斷,比如一個網卡所傳來的數據加載到內核的某個內存區域中,比如網卡緩沖或者內核緩沖區當中,而后是否立即處理需要看其緊急程序,如果不是非常緊急一旦處理結束,cpu繼續運行之前中斷時被打斷的進程,當進程處理完了再由內核著手
無論等待的時間與否,只要時間消耗完必須切換回去,讓其他進程運行,等其他進程執行完成之后再由這個沒有執行完的請求繼續
?
·現在的問題是,當運行完后是否處理中斷:
需要取決于內核調度,所以下半部并不是立即執行的而是由內核調度決定的
?
?http://?
例:
?
假如io是個網卡,有人發起了ping請求,或者web服務上傳的請求,這個請求包含多個報文,報文不能立即全部被接受進來,那么來一個報文,網卡則接收到一個信號,接收到一個信號則發起一個中斷,那cpu則切換到中斷上下文由內核將數據讀取到緩沖區中,來一個報文中斷一次,很顯然cpu會頻繁中斷,因此生產能力受到影響,因此有了第三種方式 DMA
?
3.DMA
事實上多信號或報文進行處理時,內核指定cpu告知DMA 內存訪問控制器,由他來指揮,將數據都放到已經分配到內存區域中某個連續的空間中,所以DMA取得了總線控制權,將數據都讀取到內存中,當某一事件結束后,中斷控制器自動向cpu發起請求,告知任務已完成,接下來由內核進行處理
?
實際中的io設備不止一個,硬盤可能有多快 鍵盤 網卡等,因此這些io設備的中斷注冊的時候,有可能被分配到多個cpu中,以避免cpu被頻繁打斷的
?
·這樣就有另外的問題,比如:
如果有多個核心的話,打斷的有2個nginx的進程,為了保證nginx避免進程切換,于是將兩個核心隔離出來,不讓其他進程使用,但是并不意味著cpu不處理中斷,所以很有可能某些io硬件設備在其中斷注冊時仍然分配至這兩個cpu進行處理,也就是說這兩個進程仍然會被打斷,避免這類情況可以將某些中斷從這里隔離出來,不讓cpu處理中斷即可
?
網絡IO
對于網絡來講,比如一個web服務,有很多用戶對web服務器發送請求,當一個用戶請求介入進來的時候,如何確保哪些是維持的
很顯然哪些用戶請求來臨之后需要進行響應,因此第一個用戶請求接入進來還沒來得及響應第二個用戶又接入進來,在處理時有可能先處理先來的請求,那如何知道有多少個請求,每個請求都是誰的:
?
在內存中使用特定的內存數據結構來維持每個鏈接,因此簡單的說當用戶請求接入進來之后內核要為其創建一個套接字文件,這個套接字建立兩段: 源地址源端口 以及 目標地址目標端口,而后將繪話轉交服務進行處理,當處理結束之后內核要重新封裝一個響應報文發送給用戶,這里標記是要考內存中標識的信息進行追蹤的,這就是為什么此前說到的套接字文件,它需要占據一個文件描述符,為了保證當前系統上能夠公平的使用多個文件,所以系統默認設定了單個進程能夠打開單個文件描述符的數量是有上限的,因此某進程非常繁忙,需要大量處理請求,需要調整文件描述符
?
?yijiu
參數的調整
?
如圖所示,當cpu有多顆時,因此兩顆cpu 8個核心,cpu 0-3 在第一顆 ,cpu4-7 在第二顆cpu上
?yijiu
實現本地內存訪問,有三個步驟:
1.給出本地內存控制器的地址
2.內存控制器設置對內存地址的訪問
3.cpu執行操作
?
如果跨節點訪問,需要多出一個步驟,而這多出的步驟則花費的時間多的多
?
使用taskset設置親緣性
如何標識處理器
處理器是由掩碼進行標志,通常是16進制的,因此0x00000001 表示處理器0
0x00000003 代表處理器 0 和 1
?#盜貼死全家
執行以下命令,使用處理器或者您要捆綁到的處理器掩碼替換 mask ,使 用您要更改親和性的進程的進程 ID 替換 pid。
taskset -p mask ?pid
??#盜貼死全家
列:
使用 -c 參數指定綁定在哪個cpu上:
taskset -c 0,5,7-9 ?mask ?pid
?
如下所示:
將httpd進程進行綁定
?
[root@test ~]# /etc/init.d/httpd start
Starting httpd:??????????????????????????????????????????? [? OK? ]
[root@test ~]# ps -aux | grep httpd
Warning: bad syntax, perhaps a bogus '-'? See /usr/share/doc/procps-3.2.8/FAQ
root????? 2071? 0.1? 1.0 297764 10772 ???????? Ss?? 18:52?? 0:00 /usr/sbin/httpd
apache??? 2073? 0.0? 0.5 297764? 5876 ???????? S??? 18:52?? 0:00 /usr/sbin/httpd
apache??? 2074? 0.0? 0.5 297764? 5876 ???????? S??? 18:52?? 0:00 /usr/sbin/httpd
apache??? 2075? 0.0? 0.5 297764? 5876 ???????? S??? 18:52?? 0:00 /usr/sbin/httpd
apache??? 2076? 0.0? 0.5 297764? 5876 ???????? S??? 18:52?? 0:00 /usr/sbin/httpd
apache??? 2077? 0.0? 0.5 297764? 5876 ???????? S??? 18:52?? 0:00 /usr/sbin/httpd
apache??? 2078? 0.0? 0.5 297764? 5876 ???????? S??? 18:52?? 0:00 /usr/sbin/httpd
apache??? 2079? 0.0? 0.5 297764? 5876 ???????? S??? 18:52?? 0:00 /usr/sbin/httpd
apache??? 2080? 0.0? 0.5 297764? 5876 ???????? S??? 18:52?? 0:00 /usr/sbin/httpd
root????? 2084? 0.0? 0.0 105300?? 840 pts/0??? S+?? 18:52?? 0:00 grep httpd
?
httpd有很多進程其中有個進程id號位2073
那此時2073到底運行在哪個cpu上:
使用ps -axo pid,psr 進行觀測,psr是進程運行在哪個處理器上
?
當前我們系統只有2顆cpu
[root@test ~]# grep processor /proc/cpuinfo
processor???? : 0
processor???? : 1
?
[root@test ~]# ps -axo pid,psr | grep 2073
?2073?? 0
?
可以看到是運行在第0顆cpu上的?#盜 貼 死全家
如果沒有做調度,它會一直工作在這個cpu上,如果被大量訪問,有可能被調度到不同的cpu上去
?
那么我們想將這個進程運行在cpu1上:
[root@test ~]# taskset -pc 1 2073????
pid 2073's current affinity list: 0,1 ? ???#表示2073id號可以在 0-1進行調度
pid 2073's new affinity list: 1 ? ? ? ? #表示這個id綁定在cpu1上
?
激活進程不然處于休眠狀態,需要對其作ab壓測即可
?
當然也可以在執行某一進程的時候明確指定使用哪個cpu
將參數加上mask 即可
taskset mask --program(啟動程序)
直接運行在指定的cpu上
?
例:
taskset -c 0,2 httpd
然后查看進程
ps -aux | grep httpd
ps axo pid,psr | grep -E "pid|pid"
?
對其作壓力測試頁不會發生改變,只在兩個cpu上進行調度
?
中斷和IRQ調節?#盜貼死全家
?
IRQ : 為中斷請求
查看當前系統有哪些中斷,而這些中斷都綁定在哪些cpu上
中斷在/proc/interrupts?#盜貼死全家?可以看到:
?
[root@test ~]# cat /proc/interrupts
?????????? CPU0?????? CPU1?????
? 0:??????? 148????????? 0?? IO-APIC-edge????? timer
? 1:????????? 7????????? 1?? IO-APIC-edge????? i8042
? 3:????????? 0????????? 1?? IO-APIC-edge??
? 4:????????? 1????????? 0?? IO-APIC-edge??
? 7:????????? 0????????? 0?? IO-APIC-edge????? parport0
? 8:????????? 0????????? 0?? IO-APIC-edge????? rtc0
? 9:????????? 0????????? 0?? IO-APIC-fasteoi?? acpi
12:??????? 105????????? 1?? IO-APIC-edge????? i8042
14:??????? 212??????? 159?? IO-APIC-edge????? ata_piix
15:???????? 84???????? 24?? IO-APIC-edge????? ata_piix
16:????????? 0????????? 0?? IO-APIC-fasteoi?? Ensoniq AudioPCI
17:????? 25409?????? 1042?? IO-APIC-fasteoi?? ehci_hcd:usb1, ioc0
18:???????? 39????????? 0?? IO-APIC-fasteoi?? uhci_hcd:usb2
19:????? 32792?????? 2651?? IO-APIC-fasteoi?? eth0, eth1
24: ?????????0????????? 0?? PCI-MSI-edge????? pciehp
25:????????? 0????????? 0?? PCI-MSI-edge????? pciehp
26:????????? 0????????? 0?? PCI-MSI-edge????? pciehp
27:????????? 0????????? 0?? PCI-MSI-edge????? pciehp
28:????????? 0????????? 0?? PCI-MSI-edge????? pciehp
29:????????? 0????????? 0?? PCI-MSI-edge????? pciehp
30:????????? 0????????? 0?? PCI-MSI-edge????? pciehp
31:????????? 0????????? 0?? PCI-MSI-edge????? pciehp
32:????????? 0????????? 0?? PCI-MSI-edge????? pciehp
33:????????? 0????????? 0?? PCI-MSI-edge????? pciehp
34:????????? 0????????? 0?? PCI-MSI-edge????? pciehp
35:????????? 0????????? 0?? PCI-MSI-edge????? pciehp
36:????????? 0????????? 0?? PCI-MSI-edge????? pciehp
37:????????? 0????????? 0?? PCI-MSI-edge??? ??pciehp
38:????????? 0????????? 0?? PCI-MSI-edge????? pciehp
39:????????? 0????????? 0?? PCI-MSI-edge????? pciehp
40:????????? 0????????? 0?? PCI-MSI-edge????? pciehp
41:????????? 0????????? 0?? PCI-MSI-edge????? pciehp
42:????????? 0????????? 0?? PCI-MSI-edge????? pciehp
43:????????? 0????????? 0?? PCI-MSI-edge????? pciehp
44:????????? 0????????? 0?? PCI-MSI-edge????? pciehp
45:????????? 0????????? 0?? PCI-MSI-edge????? pciehp
46:????????? 0????????? 0?? PCI-MSI-edge????? pciehp
47:????????? 0????????? 0 ??PCI-MSI-edge????? pciehp
48:????????? 0????????? 0?? PCI-MSI-edge????? pciehp
49:????????? 0????????? 0?? PCI-MSI-edge????? pciehp
50:????????? 0????????? 0?? PCI-MSI-edge????? pciehp
51:????????? 0????????? 0?? PCI-MSI-edge????? pciehp
52:????????? 0?? ???????0?? PCI-MSI-edge????? pciehp
53:????????? 0????????? 0?? PCI-MSI-edge????? pciehp
54:????????? 0????????? 0?? PCI-MSI-edge????? pciehp
55:????????? 0????????? 0?? PCI-MSI-edge????? pciehp
NMI:????????? 0????????? 0?? Non-maskable interrupts
LOC:??? ??85179????? 56618?? Local timer interrupts
SPU:????????? 0????????? 0?? Spurious interrupts
PMI:????????? 0????????? 0?? Performance monitoring interrupts
IWI:????????? 0????????? 0?? IRQ work interrupts
RES:?????? 5023?????? 5078?? Rescheduling interrupts
CAL:???????? 60?????? 8613?? Function call interrupts
TLB:?????? 1608?????? 2010?? TLB shootdowns
TRM:????????? 0????????? 0?? Thermal event interrupts
THR:????????? 0????????? 0?? Threshold APIC interrupts
MCE:????????? 0????????? 0?? Machine check exceptions
MCP:???????? 18???????? 18?? Machine check polls
ERR:????????? 0
MIS:????????? 0
?
?
可以看到每個中斷號,中斷是由哪個硬件設備發出的都有線上
[root@test ~]# cat /proc/interrupts? | grep eth
19:????? 32928?????? 2736?? IO-APIC-fasteoi?? eth0, eth1
?
/proc/interrupts顯示了每個io設備中的每個cpu曾經處理過的設備的中斷數
可以看到17號中斷被處理的比較多:
17:????? 25409?????? 1042?? IO-APIC-fasteoi?? ehci_hcd:usb1, ioc0
?
因此不同的硬件設備,由哪個cpu處理是分配好的
IRQ中有類似于 smp_affinity屬性,用于定義通過某個中斷綁定在cpu上
當接收到一個中斷以后,這個中斷該由中斷路由進行處理(ISR)?
因此IRQ的數值中斷近似性值是保存的相關的 /proc/irq/某個中斷號/smp_affinity文件中
?
?
以eth0為例:
[root@test ~]# grep eth0 /proc/interrupts
19:????? 33226?????? 2915?? IO-APIC-fasteoi?? eth0, eth1
?
里面定義了eth0和eth1 的網卡中斷號是19,然后找irq為19的smp_affinity文件:
[root@test ~]# cat /proc/irq/19/smp_affinity
03
其中 f為所有cpu,如果是0是第0個cpu , 1就為1號cpu
?
有些特定的硬件,在啟動的時候就已經注冊在cpu上,但是在公共硬件,比如網卡或硬盤,有可能是由內核進行調度的并且是不斷進行調度的
如果想設定一個特定cpu的話,將其隔離出來,要保證沒有被任何中斷被處理
去掃描每個目錄的中斷號,只要它的值對應的是這個cpu編號的話,就挑出來再調整到其他cpu上去
?
只需要echo 一個 cpu的編號直接到對應的中斷號的smp_affinity文件里即可
[root@test ~]# echo 0 > /proc/irq/19/smp_affinity
?
這樣的過程被稱為隔離中斷,也可以叫中斷的親緣性
?
?#盜貼死全家
?
?本文轉自zuzhou 51CTO博客,原文鏈接:http://blog.51cto.com/yijiu/1702204
?
總結
以上是生活随笔為你收集整理的CPU亲缘性及网卡中断绑定的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 生成唯一id号解决方法
- 下一篇: yarn container写token