CPU親緣性及網卡中斷綁定

#####編輯器依舊那麼難用 難用 難用~~################node

##################################################nginx

 

CPU親緣性及網卡中斷綁定web

每一個CPU的每一個核心都會被識別成一個邏輯CPU,由一個核心會存在超線程的功能,因此一個物理核心會表現成爲多個cpuapache

 

多個cpu之間是如何通訊的服務器

首先了解幾個概念網絡

smp: 對等的訪問內存空間,事實上cpu訪問內存是經過內存控制器的芯片進行的數據結構

numa: 非一致性內存訪問機制socket

 http://yijiu.blog.51cto.com編輯器

numa體系ide

簡單來說是每一個物理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

參數的調整

 

spacer.gif

如圖所示,當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

 

這樣的過程被稱爲隔離中斷,也能夠叫中斷的親緣性

 

 #盜貼死全家

相關文章
相關標籤/搜索