❶ linux系統性能怎麼優化
linux系統性能怎麼優化
一、前提
我們可以在文章的開始就列出一個列表,列出可能影響Linux操作系統性能的一些調優參數,但這樣做其實並沒有什麼價值。因為性能調優是一個非常困難的任務,它要求對硬體、操作系統、和應用都有著相當深入的了解。如果性能調優非常簡單的話,那些我們要列出的調優參數早就寫入硬體的微碼或者操作系統中了,我們就沒有必要再繼續讀這篇文章了。正如下圖所示,伺服器的性能受到很多因素的影響。
當面對一個使用單獨IDE硬碟的,有20000用戶的資料庫伺服器時,即使我們使用數周時間去調整I/O子系統也是徒勞無功的,通常一個新的驅動或者應用程序的一個更新(如SQL優化)卻可以使這個伺服器的性能得到明顯的提升。正如我們前面提到的,不要忘記系統的性能是受多方面因素影響的。理解操作系統管理系統資源的方法將幫助我們在面對問題時更好的判斷應該對哪個子系統進行調整。
二、Linux的CPU調度
任何計算機的基本功能都十分簡單,那就是計算。為了實現計算的功能就必須有一個方法去管理計算資源、處理器和計算任務(也被叫做線程或者進程)。非常感謝Ingo Molnar,他為Linux內核帶來了O(1)CPU調度器,區別於舊有的O(n)調度器,新的調度器是動態的,可以支持負載均衡,並以恆定的速度進行操作。
新調度器的可擴展性非常好,無論進程數量或者處理器數量,並且調度器本身的系統開銷更少。新調取器的演算法使用兩個優先順序隊列。
引用
・活動運行隊列
・過期運行隊列
調度器的一個重要目標是根據優先順序許可權有效地為進程分配CPU 時間片,當分配完成後它被列在CPU的運行隊列中,除了 CPU 的運行隊列之外,還有一個過期運行隊列。當活動運行隊列中的一個任務用光自己的時間片之後,它就被移動到過期運行隊列中。在移動過程中,會對其時間片重新進行計算。如果活動運行隊列中已經沒有某個給定優先順序的任務了,那麼指向活動運行隊列和過期運行隊列的指針就會交換,這樣就可以讓過期優先順序列表變成活動優先順序的列表。通常互動式進程(相對與實時進程而言)都有一個較高的優先順序,它佔有更長的時間片,比低優先順序的進程獲得更多的計算時間,但通過調度器自身的調整並不會使低優先順序的進程完全被餓死。新調度器的優勢是顯著的改變Linux內核的可擴展性,使新內核可以更好的處理一些有大量進程、大量處理器組成的企業級應用。新的O(1)調度器包含仔2.6內核中,但是也向下兼容2.4內核。
新調度器另外一個重要的優勢是體現在對NUMA(non-uniform memory architecture)和SMP(symmetric multithreading processors)的支持上,例如INTEL@的超線程技術。
改進的NUMA支持保證了負載均衡不會發生在CECs或者NUMA節點之間,除非發生一個節點的超出負載限度。
三、Linux的內存架構
今天我們面對選擇32位操作系統還是64位操作系統的情況。對企業級用戶它們之間最大的區別是64位操作系統可以支持大於4GB的內存定址。從性能角度來講,我們需要了解32位和64位操作系統都是如何進行物理內存和虛擬內存的映射的。
在上面圖示中我們可以看到64位和32位Linux內核在定址上有著顯著的不同。
在32位架構中,比如IA-32,Linux內核可以直接定址的范圍只有物理內存的第一個GB(如果去掉保留部分還剩下896MB),訪問內存必須被映射到這小於1GB的所謂ZONE_NORMAL空間中,這個操作是由應用程序完成的。但是分配在ZONE_HIGHMEM中的內存頁將導致性能的降低。
在另一方面,64位架構比如x86-64(也稱作EM64T或者AMD64)。ZONE_NORMAL空間將擴展到64GB或者128GB(實際上可以更多,但是這個數值受到操作系統本身支持內存容量的限制)。正如我們看到的,使用64位操作系統我們排除了因ZONE_HIGHMEM部分內存對性能的影響的情況。
實際中,在32位架構下,由於上面所描述的內存定址問題,對於大內存,高負載應用,會導致死機或嚴重緩慢等問題。雖然使用hugemen核心可緩解,但採取x86_64架構是最佳的解決辦法。
四、虛擬內存管理
因為操作系統將內存都映射為虛擬內存,所以操作系統的物理內存結構對用戶和應用來說通常都是不可見的。如果想要理解Linux系統內存的調優,我們必須了解Linux的虛擬內存機制。應用程序並不分配物理內存,而是向Linux內核請求一部分映射為虛擬內存的內存空間。如下圖所示虛擬內存並不一定是映射物理內存中的空間,如果應用程序有一個大容量的請求,也可能會被映射到在磁碟子系統中的swap空間中。
另外要提到的是,通常應用程序不直接將數據寫到磁碟子系統中,而是寫入緩存和緩沖區中。Bdflush守護進程將定時將緩存或者緩沖區中的數據寫到硬碟上。
Linux內核處理數據寫入磁碟子系統和管理磁碟緩存是緊密聯系在一起的。相對於其他的操作系統都是在內存中分配指定的一部分作為磁碟緩存,Linux處理內存更加有效,默認情況下虛擬內存管理器分配所有可用內存空間作為磁碟緩存,這就是為什麼有時我們觀察一個配置有數G內存的Linux系統可用內存只有20MB的原因。
同時Linux使用swap空間的機制也是相當高效率的,如上圖所示虛擬內存空間是由物理內存和磁碟子系統中的swap空間共同組成的。如果虛擬內存管理器發現一個已經分配完成的內存分頁已經長時間沒有被調用,它將把這部分內存分頁移到swap空間中。經常我們會發現一些守護進程,比如getty,會隨系統啟動但是卻很少會被應用到。這時為了釋放昂貴的主內存資源,系統會將這部分內存分頁移動到swap空間中。上述就是Linux使用swap空間的機制,當swap分區使用超過50%時,並不意味著物理內存的使用已經達到瓶頸了,swap空間只是Linux內核更好的使用系統資源的一種方法。
簡單理解:Swap usage只表示了Linux管理內存的有效性。對識別內存瓶頸來說,Swap In/Out才是一個比較又意義的依據,如果Swap In/Out的值長期保持在每秒200到300個頁面通常就表示系統可能存在內存的瓶頸。下面的事例是好的狀態:
引用
# vmstat
procs ———–memory————- —swap– —–io—- –system– —-cpu—-
r b swpd free buff cache si so bi bo in cs us sy id wa
1 0 5696 6904 28192 50496 0 0 88 117 61 29 11 8 80 1
五、模塊化的I/O調度器
就象我們知道的Linux2.6內核為我們帶來了很多新的特性,這其中就包括了新的I/O調度機制。舊的2.4內核使用一個單一的I/O調度器,2.6 內核為我們提供了四個可選擇的I/O調度器。因為Linux系統應用在很廣闊的范圍里,不同的應用對I/O設備和負載的要求都不相同,例如一個筆記本電腦和一個10000用戶的資料庫伺服器對I/O的要求肯定有著很大的區別。
引用
(1).Anticipatory
anticipatory I/O調度器創建假設一個塊設備只有一個物理的查找磁頭(例如一個單獨的SATA硬碟),正如anticipatory調度器名字一樣,anticipatory調度器使用「anticipatory」的演算法寫入硬碟一個比較大的數據流代替寫入多個隨機的小的數據流,這樣有可能導致寫 I/O操作的一些延時。這個調度器適用於通常的一些應用,比如大部分的個人電腦。
(2).Complete Fair Queuing (CFQ)
Complete Fair Queuing(CFQ)調度器是Red Flag DC Server 5使用的標准演算法。CFQ調度器使用QoS策略為系統內的所有任務分配相同的帶寬。CFQ調度器適用於有大量計算進程的多用戶系統。它試圖避免進程被餓死和實現了比較低的延遲。
(3).Deadline
deadline調度器是使用deadline演算法的輪詢的調度器,提供對I/O子系統接近實時的操作,deadline調度器提供了很小的延遲和維持一個很好的磁碟吞吐量。如果使用deadline演算法請確保進程資源分配不會出現問題。
(4).NOOP
NOOP調度器是一個簡化的調度程序它只作最基本的合並與排序。與桌面系統的關系不是很大,主要用在一些特殊的軟體與硬體環境下,這些軟體與硬體一般都擁有自己的調度機制對內核支持的要求很小,這很適合一些嵌入式系統環境。作為桌面用戶我們一般不會選擇它。
六、網路子系統
新的網路中斷緩和(NAPI)對網路子系統帶來了改變,提高了大流量網路的性能。Linux內核在處理網路堆棧時,相比降低系統佔用率和高吞吐量更關注可靠性和低延遲。所以在某些情況下,Linux建立一個防火牆或者文件、列印、資料庫等企業級應用的性能可能會低於相同配置的Windows伺服器。
在傳統的處理網路封包的方式中,如下圖藍色箭頭所描述的,一個乙太網封包到達網卡介面後,如果MAC地址相符合會被送到網卡的緩沖區中。網卡然後將封包移到操作系統內核的網路緩沖區中並且對CPU發出一個硬中斷,CPU會處理這個封包到相應的網路堆棧中,可能是一個TCP埠或者Apache應用中。
這是一個處理網路封包的簡單的流程,但從中我們可以看到這個處理方式的缺點。正如我們看到的,每次適合網路封包到達網路介面都將對CPU發出一個硬中斷信號,中斷CPU正在處理的其他任務,導致切換動作和對CPU緩存的操作。你可能認為當只有少量的網路封包到達網卡的情況下這並不是個問題,但是千兆網路和現代的應用將帶來每秒鍾成千上萬的網路數據,這就有可能對性能造成不良的影響。
正是因為這個情況,NAPI在處理網路通訊的時候引入了計數機制。對第一個封包,NAPI以傳統的方式進行處理,但是對後面的封包,網卡引入了POLL 的輪詢機制:如果一個封包在網卡DMA環的緩存中,就不再為這個封包申請新的中斷,直到最後一個封包被處理或者緩沖區被耗盡。這樣就有效的減少了因為過多的中斷CPU對系統性能的影響。同時,NAPI通過創建可以被多處理器執行的軟中斷改善了系統的可擴展性。NAPI將為大量的企業級多處理器平台帶來幫助,它要求一個啟用NAPI的驅動程序。在今天很多驅動程序默認沒有啟用NAPI,這就為我們調優網路子系統的性能提供了更廣闊的空間。
七、理解Linux調優參數
因為Linux是一個開源操作系統,所以又大量可用的性能監測工具。對這些工具的選擇取決於你的個人喜好和對數據細節的要求。所有的性能監測工具都是按照同樣的規則來工作的,所以無論你使用哪種監測工具都需要理解這些參數。下面列出了一些重要的參數,有效的理解它們是很有用處的。
(1)處理器參數
引用
・CPU utilization
這是一個很簡單的參數,它直觀的描述了每個CPU的利用率。在xSeries架構中,如果CPU的利用率長時間的超過80%,就可能是出現了處理器的瓶頸。
・Runable processes
這個值描述了正在准備被執行的進程,在一個持續時間里這個值不應該超過物理CPU數量的10倍,否則CPU方面就可能存在瓶頸。
・Blocked
描述了那些因為等待I/O操作結束而不能被執行的進程,Blocked可能指出你正面臨I/O瓶頸。
・User time
描述了處理用戶進程的百分比,包括nice time。如果User time的值很高,說明系統性能用在處理實際的工作。
・System time
描述了CPU花費在處理內核操作包括IRQ和軟體中斷上面的百分比。如果system time很高說明系統可能存在網路或者驅動堆棧方面的瓶頸。一個系統通常只花費很少的時間去處理內核的操作。
・Idle time
描述了CPU空閑的百分比。
・Nice time
描述了CPU花費在處理re-nicing進程的百分比。
・Context switch
系統中線程之間進行交換的數量。
・Waiting
CPU花費在等待I/O操作上的總時間,與blocked相似,一個系統不應該花費太多的時間在等待I/O操作上,否則你應該進一步檢測I/O子系統是否存在瓶頸。
・Interrupts
Interrupts 值包括硬Interrupts和軟Interrupts,硬Interrupts會對系統性能帶來更多的不利影響。高的Interrupts值指出系統可能存在一個軟體的瓶頸,可能是內核或者驅動程序。注意Interrupts值中包括CPU時鍾導致的中斷(現代的xServer系統每秒1000個 Interrupts值)。
(2)內存參數
引用
・Free memory
相比其他操作系統,Linux空閑內存的值不應該做為一個性能參考的重要指標,因為就像我們之前提到過的,Linux內核會分配大量沒有被使用的內存作為文件系統的緩存,所以這個值通常都比較小。
・Swap usage
這 個值描述了已經被使用的swap空間。Swap usage只表示了Linux管理內存的有效性。對識別內存瓶頸來說,Swap In/Out才是一個比較又意義的依據,如果Swap In/Out的值長期保持在每秒200到300個頁面通常就表示系統可能存在內存的瓶頸。
・Buffer and cache
這個值描述了為文件系統和塊設備分配的緩存。在Red Flag DC Server 5版本中,你可以通過修改/proc/sys/vm中的page_cache_tuning來調整空閑內存中作為緩存的數量。
・Slabs
描述了內核使用的內存空間,注意內核的頁面是不能被交換到磁碟上的。
・Active versus inactive memory
提供了關於系統內存的active內存信息,Inactive內存是被kswapd守護進程交換到磁碟上的空間。
(3)網路參數
引用
・Packets received and sent
這個參數表示了一個指定網卡接收和發送的數據包的數量。
・Bytes received and sent
這個參數表示了一個指定網卡接收和發送的數據包的位元組數。
・Collisions per second
這個值提供了發生在指定網卡上的網路沖突的數量。持續的出現這個值代表在網路架構上出現了瓶頸,而不是在伺服器端出現的問題。在正常配置的網路中沖突是非常少見的,除非用戶的網路環境都是由hub組成。
・Packets dropped
這個值表示了被內核丟掉的數據包數量,可能是因為防火牆或者是網路緩存的缺乏。
・Overruns
Overruns表達了超出網路介面緩存的次數,這個參數應該和packets dropped值聯繫到一起來判斷是否存在在網路緩存或者網路隊列過長方面的瓶頸。
・Errors 這個值記錄了標志為失敗的幀的數量。這個可能由錯誤的網路配置或者部分網線損壞導致,在銅口千兆乙太網環境中部分網線的損害是影響性能的一個重要因素。
(4)塊設備參數
引用
・Iowait
CPU等待I/O操作所花費的時間。這個值持續很高通常可能是I/O瓶頸所導致的。
・Average queue length
I/O請求的數量,通常一個磁碟隊列值為2到3為最佳情況,更高的值說明系統可能存在I/O瓶頸。
・Average wait
響應一個I/O操作的平均時間。Average wait包括實際I/O操作的時間和在I/O隊列里等待的時間。
・Transfers per second
描述每秒執行多少次I/O操作(包括讀和寫)。Transfers per second的值與kBytes per second結合起來可以幫助你估計系統的平均傳輸塊大小,這個傳輸塊大小通常和磁碟子系統的條帶化大小相符合可以獲得最好的性能。
・Blocks read/write per second
這個值表達了每秒讀寫的blocks數量,在2.6內核中blocks是1024bytes,在早些的內核版本中blocks可以是不同的大小,從512bytes到4kb。
・Kilobytes per second read/write
按照kb為單位表示讀寫塊設備的實際數據的數量。
❷ 負載均衡時linux下都採用哪些方法做存儲
1、bond
bond是Linux內核自帶的多網卡聚合功能。這個功能可以把多個網卡整合成一個虛擬網卡從而同時利用多塊網卡傳輸數據。bond有多種不同的模式用以適應不同的情況。bond主要是從L2鏈路層考慮的,因此可以bond的網卡通常要連到同一個交換機上。
2、iproute2(ip命令)中的多路由
可以使用ip命令中的nexthop選項非常簡單的實現負載均衡。nexthop可以為同一個目的地址指定多條路由,並可以指定每條路由的權重。之後系統會根據權重為數據選擇某條路由。
例如:ip route add default nexthop via $P1 dev $IF1 weight 1 nexthop via $P2 dev $IF2 weight 1
這條命令定義默認路由有ip1:if1和ip2:if2兩條路徑,且這兩條路徑的權重相同。
利用ip命令實現上邊這樣簡單的負載均衡是非常方便的,但是ip命令畢竟是一個網路層命令,因此它是無法根據運輸層(埠號)進行負載均衡的。
3、iptables+iproute2
提起iptables大多數人都只用過其中的filter表和nat表,而對於mangle表則很少有人使用。然後使用mangle表是可以非常方便地實現靈活負載均衡的。
iptables的mangle表用來修改數據包的一些標識,可以修改的標識有:dscp(區分服務類型)、ToS(服務類型)、mark(標記)。前兩者是ip頭的QoS相關標志位,主要用於ip層的qos實現,但是目前這兩個標志位極少被用到,通常都會被忽略。而第三個(mark)則是由linux內核實現的對數據包的標記。因為是由linux內核實現的,因此這個標記只能在本機使用,並非數據包的一部分,出了本機這個標記就不存在了。
iptables實現負載均衡主要是通過修改mark標記來實現。iproute2可以針對數據包的不同mark定義專門的策略路由表,因此我們可以把去往不同介面的路由寫入適用不同mark的策略路由表中,之後linux就可以根據數據包的mark來決定數據包要走的路由了。
例如:
首先,為所有進入本機的目的埠號為25的tcp包打上「1」標記:
iptables -A PREROUTING -t mangle -p tcp --dport 25 -j MARK --set-mark 1
添加路由規則規定標記為1的數據包使用路由表200
ip rule add fwmark 1 table 200
在200路由表中添加路由
ip route add default via 192.168.1.1 dev ppp0 table 200
同理,為所有進入本機的目的埠號為80的tcp包打上「2」標記
iptables -A PREROUTING -t mangle -p tcp --dport 80 -j MARK --set-mark 2
添加相關路由,方法同上:
ip rule add fwmark 2 table 200
ip route add default via 192.168.2.1 dev wlan0 table 200
這樣子一來以後所有的埠號為25的包都會走192.168.1.1 dev ppp0路由,而所有埠號為80的數據包則會走192.168.2.1
dev
wlan0路由,從而實現了針對埠號的負載均衡。同理,也可以利用iptables實現針對源(目的)地址、協議、介面的負載均衡,真的非常的方便。
4、tc
流量控制器TC(Traffic
Control)用於Linux內核的流量控制,它利用隊列規定建立處理數據包的隊列,並定義隊列中的數據包被發送的方式,
從而實現對流量的控制。TC命令通過建立篩選器(filter)、分類器(class)、隊列(qdisc)這三個對象來實現對流量的控制。具體的講就是,通過篩選器決定哪些數據包進入到哪些分類的隊列中,之後再按照一定的規則將數據包從各個分類的隊列中發送出去。盡管tc的主要功能在於流量控制,但是我們可以通過把一個隊列建立在多個網卡上來實現流量的負載均衡。
例如:
在eth1上建立一個隊列:
tc qdisc add dev eth1 root teql0
在eth2上建立同樣的隊列
tc qdisc add dev eth2 root teql0
啟動設備teql0
ip link set dev teql0 up
通過這三條命令,所有發往teql0的流量都會在eth1和eth2之間進行負載均衡發送。
應該說,tc是一個相當強大復雜的工具,但是tc的主要功能還是在於流量控制。
5、LVS
LVS(Linux virtual
machine)是一套集成在Linux內核中的負載均衡服務。LVS通過部署負載均衡伺服器在網路層截獲並修改報文並依據一定規則分發給伺服器集群中伺服器來實現負載均衡。LVS主要用於web伺服器的負載均衡,通過LVS,用戶的請求可以被調度到伺服器集群的多個伺服器上去,並且用戶認為自己始終在跟唯一一台伺服器進行通信。LVS與前邊幾種負載均衡技術最大的差別在於,LVS有非常具體的應用場景,即web伺服器集群。
❸ linux 用戶進程 可以搶占內核進程嗎
1.2.1 調度過程中關閉內核搶占
我們在上一篇linux內核主調度器schele(文章鏈接, CSDN, Github)中在分析主調度器的時候, 我們會發現內核在進行調度之前都會通過preempt_disable關閉內核搶占, 而在完成調度工作後, 又會重新開啟內核搶占
參見主調度器函數schele
do {
preempt_disable(); /* 關閉內核搶占 */
__schele(false); /* 完成調度 */
sched_preempt_enable_no_resched(); /* 開啟內核搶占 */
} while (need_resched()); /* 如果該進程被其他進程設置了TIF_NEED_RESCHED標志,則函數重新執行進行調度 */123456123456
這個很容易理解, 我們在內核完成調度器過程中, 這時候如果發生了內核搶占, 我們的調度會被中斷, 而調度卻還沒有完成, 這樣會丟失我們調度的信息.
1.2.2 調度完成檢查need_resched看是否需要重新調度
而同樣我們可以看到, 在調度完成後, 內核會去判斷need_resched條件, 如果這個時候為真, 內核會重新進程一次調度.
這個的原因, 我們在前一篇博客中, 也已經說的很明白了,
內核在thread_info的flag中設置了一個標識來標志進程是否需要重新調度, 即重新調度need_resched標識TIF_NEED_RESCHED, 內核在即將返回用戶空間時會檢查標識TIF_NEED_RESCHED標志進程是否需要重新調度,如果設置了,就會發生調度, 這被稱為用戶搶占
2 非搶占式和可搶占式內核
為了簡化問題,我使用嵌入式實時系統uC/OS作為例子
首先要指出的是,uC/OS只有內核態,沒有用戶態,這和Linux不一樣
多任務系統中, 內核負責管理各個任務, 或者說為每個任務分配CPU時間, 並且負責任務之間的通訊.
內核提供的基本服務是任務切換. 調度(Scheler),英文還有一詞叫dispatcher, 也是調度的意思.
這是內核的主要職責之一, 就是要決定該輪到哪個任務運行了. 多數實時內核是基於優先順序調度法的, 每個任務根據其重要程度的不同被賦予一定的優先順序. 基於優先順序的調度法指,CPU總是讓處在就緒態的優先順序最高的任務先運行. 然而, 究竟何時讓高優先順序任務掌握CPU的使用權, 有兩種不同的情況, 這要看用的是什麼類型的內核, 是不可剝奪型的還是可剝奪型內核
2.1 非搶占式內核
非搶占式內核是由任務主動放棄CPU的使用權
非搶占式調度法也稱作合作型多任務, 各個任務彼此合作共享一個CPU. 非同步事件還是由中斷服務來處理. 中斷服務可以使一個高優先順序的任務由掛起狀態變為就緒狀態.
但中斷服務以後控制權還是回到原來被中斷了的那個任務, 直到該任務主動放棄CPU的使用權時,那個高優先順序的任務才能獲得CPU的使用權。非搶占式內核如下圖所示.
非搶占式內核的優點有
中斷響應快(與搶占式內核比較);
允許使用不可重入函數;
幾乎不需要使用信號量保護共享數據, 運行的任務佔有CPU,不必擔心被別的任務搶占。這不是絕對的,在列印機的使用上,仍需要滿足互斥條件。
非搶占式內核的缺點有
任務響應時間慢。高優先順序的任務已經進入就緒態,但還不能運行,要等到當前運行著的任務釋放CPU
非搶占式內核的任務級響應時間是不確定的,不知道什麼時候最高優先順序的任務才能拿到CPU的控制權,完全取決於應用程序什麼時候釋放CPU
2.2 搶占式內核
使用搶占式內核可以保證系統響應時間. 最高優先順序的任務一旦就緒, 總能得到CPU的使用權。當一個運行著的任務使一個比它優先順序高的任務進入了就緒態, 當前任務的CPU使用權就會被剝奪,或者說被掛起了,那個高優先順序的任務立刻得到了CPU的控制權。如果是中斷服務子程序使一個高優先順序的任務進入就緒態,中斷完成時,中斷了的任務被掛起,優先順序高的那個任務開始運行。
搶占式內核如下圖所示
搶占式內核的優點有
使用搶占式內核,最高優先順序的任務什麼時候可以執行,可以得到CPU的使用權是可知的。使用搶占式內核使得任務級響應時間得以最優化。
搶占式內核的缺點有:
不能直接使用不可重入型函數。調用不可重入函數時,要滿足互斥條件,這點可以使用互斥型信號量來實現。如果調用不可重入型函數時,低優先順序的任務CPU的使用權被高優先順序任務剝奪,不可重入型函數中的數據有可能被破壞。
3 linux用戶搶占
3.1 linux用戶搶占
當內核即將返回用戶空間時, 內核會檢查need_resched是否設置, 如果設置, 則調用schele(),此時,發生用戶搶占.
3.2 need_resched標識
內核如何檢查一個進程是否需要被調度呢?
內核在即將返回用戶空間時檢查進程是否需要重新調度,如果設置了,就會發生調度, 這被稱為用戶搶占, 因此內核在thread_info的flag中設置了一個標識來標志進程是否需要重新調度, 即重新調度need_resched標識TIF_NEED_RESCHED
並提供了一些設置可檢測的函數
函數
描述
定義
set_tsk_need_resched 設置指定進程中的need_resched標志 include/linux/sched.h, L2920
clear_tsk_need_resched 清除指定進程中的need_resched標志 include/linux/sched.h, L2926
test_tsk_need_resched 檢查指定進程need_resched標志 include/linux/sched.h, L2931
而我們內核中調度時常用的need_resched()函數檢查進程是否需要被重新調度其實就是通過test_tsk_need_resched實現的, 其定義如下所示
// http://lxr.free-electrons.com/source/include/linux/sched.h?v=4.6#L3093
static __always_inline bool need_resched(void)
{
return unlikely(tif_need_resched());
}
// http://lxr.free-electrons.com/source/include/linux/thread_info.h?v=4.6#L106
#define tif_need_resched() test_thread_flag(TIF_NEED_RESCHED)1234567812345678
3.3 用戶搶占的發生時機(什麼時候需要重新調度need_resched)
一般來說,用戶搶占發生幾下情況:
從系統調用返回用戶空間;
從中斷(異常)處理程序返回用戶空間
從這里我們可以看到, 用戶搶占是發生在用戶空間的搶占現象.
更詳細的觸發條件如下所示, 其實不外乎就是前面所說的兩種情況: 從系統調用或者中斷返回用戶空間
時鍾中斷處理常式檢查當前任務的時間片,當任務的時間片消耗完時,scheler_tick()函數就會設置need_resched標志;
信號量、等到隊列、completion等機制喚醒時都是基於waitqueue的,而waitqueue的喚醒函數為default_wake_function,其調用try_to_wake_up將被喚醒的任務更改為就緒狀態並設置need_resched標志。
設置用戶進程的nice值時,可能會使高優先順序的任務進入就緒狀態;
改變任務的優先順序時,可能會使高優先順序的任務進入就緒狀態;
新建一個任務時,可能會使高優先順序的任務進入就緒狀態;
對CPU(SMP)進行負載均衡時,當前任務可能需要放到另外一個CPU上運行
4 linux內核搶占
4.1 內核搶占的概念
對比用戶搶占, 顧名思義, 內核搶占就是指一個在內核態運行的進程, 可能在執行內核函數期間被另一個進程取代.
4.2 為什麼linux需要內核搶占
linux系統中, 進程在系統調用後返回用戶態之前, 或者是內核中某些特定的點上, 都會調用調度器. 這確保除了一些明確指定的情況之外, 內核是無法中斷的, 這不同於用戶進程.
如果內核處於相對耗時的操作中, 比如文件系統或者內存管理相關的任務, 這種行為可能會帶來問題. 這種情況下, 內核代替特定的進程執行相當長的時間, 而其他進程無法執行, 無法調度, 這就造成了系統的延遲增加, 用戶體驗到」緩慢」的響應. 比如如果多媒體應用長時間無法得到CPU, 則可能發生視頻和音頻漏失現象.
在編譯內核時如果啟用了對內核搶占的支持, 則可以解決這些問題. 如果高優先順序進程有事情需要完成, 那麼在啟用了內核搶占的情況下, 不僅用戶空間應用程序可以被中斷, 內核也可以被中斷,
linux內核搶占是在Linux2.5.4版本發布時加入的, 盡管使內核可搶占需要的改動特別少, 但是該機制不像搶佔用戶空間進程那樣容易實現. 如果內核無法一次性完成某些操作(例如, 對數據結構的操作), 那麼可能出現靜態條件而使得系統不一致.
內核搶占和用戶層進程被其他進程搶占是兩個不同的概念, 內核搶佔主要是從實時系統中引入的, 在非實時系統中的確也能提高系統的響應速度, 但也不是在所有情況下都是最優的,因為搶占也需要調度和同步開銷,在某些情況下甚至要關閉內核搶占, 比如前面我們將主調度器的時候, linux內核在完成調度的過程中是關閉了內核搶占的.
內核不能再任意點被中斷, 幸運的是, 大多數不能中斷的點已經被SMP實現標識出來了. 並且在實現內核搶占時可以重用這些信息. 如果內核可以被搶占, 那麼單處理器系統也會像是一個SMP系統
4.3 內核搶占的發生時機
要滿足什麼條件,kernel才可以搶佔一個任務的內核態呢?
沒持有鎖。鎖是用於保護臨界區的,不能被搶占。
Kernel code可重入(reentrant)。因為kernel是SMP-safe的,所以滿足可重入性。
內核搶占發生的時機,一般發生在:
當從中斷處理程序正在執行,且返回內核空間之前。當一個中斷處理常式退出,在返回到內核態時(kernel-space)。這是隱式的調用schele()函數,當前任務沒有主動放棄CPU使用權,而是被剝奪了CPU使用權。
當內核代碼再一次具有可搶占性的時候,如解鎖(spin_unlock_bh)及使能軟中斷(local_bh_enable)等, 此時當kernel code從不可搶占狀態變為可搶占狀態時(preemptible again)。也就是preempt_count從正整數變為0時。這也是隱式的調用schele()函數
如果內核中的任務顯式的調用schele(), 任務主動放棄CPU使用權
如果內核中的任務阻塞(這同樣也會導致調用schele()), 導致需要調用schele()函數。任務主動放棄CPU使用權
內核搶占,並不是在任何一個地方都可以發生,以下情況不能發生
內核正進行中斷處理。在Linux內核中進程不能搶佔中斷(中斷只能被其他中斷中止、搶占,進程不能中止、搶佔中斷),在中斷常式中不允許進行進程調度。進程調度函數schele()會對此作出判斷,如果是在中斷中調用,會列印出錯信息。
內核正在進行中斷上下文的Bottom Half(中斷下半部,即軟中斷)處理。硬體中斷返回前會執行軟中斷,此時仍然處於中斷上下文中。如果此時正在執行其它軟中斷,則不再執行該軟中斷。
內核的代碼段正持有spinlock自旋鎖、writelock/readlock讀寫鎖等鎖,處干這些鎖的保護狀態中。內核中的這些鎖是為了在SMP系統中短時間內保證不同CPU上運行的進程並發執行的正確性。當持有這些鎖時,內核不應該被搶占。
內核正在執行調度程序Scheler。搶占的原因就是為了進行新的調度,沒有理由將調度程序搶佔掉再運行調度程序。
內核正在對每個CPU「私有」的數據結構操作(Per-CPU date structures)。在SMP中,對於per-CPU數據結構未用spinlocks保護,因為這些數據結構隱含地被保護了(不同的CPU有不一樣的per-CPU數據,其他CPU上運行的進程不會用到另一個CPU的per-CPU數據)。但是如果允許搶占,但一個進程被搶占後重新調度,有可能調度到其他的CPU上去,這時定義的Per-CPU變數就會有問題,這時應禁搶占。
❹ Linux裡面iptables怎麼實現負載均衡
1. iptables實現負載均衡的方式:
在Linux中使用iptables完成tcp的負載均衡有兩種模式:隨機、輪詢
The statistic mole support two different modes:
random:(隨機)
the rule is skipped based on a probability
nth:(輪詢)
the rule is skipped based on a round robin algorithm
2. example