調(diào)度策略值得是大家都在ready時(shí),并且CPU已經(jīng)被調(diào)度時(shí),決定誰來運(yùn)行,誰來被調(diào)度。
網(wǎng)站建設(shè)哪家好,找成都創(chuàng)新互聯(lián)公司!專注于網(wǎng)頁設(shè)計(jì)、網(wǎng)站建設(shè)、微信開發(fā)、微信小程序、集團(tuán)企業(yè)網(wǎng)站建設(shè)等服務(wù)項(xiàng)目。為回饋新老客戶創(chuàng)新互聯(lián)還提供了湄潭免費(fèi)建站歡迎大家使用!
兩者之間有一定矛盾。
響應(yīng)的優(yōu)化,意味著高優(yōu)先級會(huì)搶占優(yōu)先級,會(huì)花時(shí)間在上下文切換,會(huì)影響吞吐。
上下文切換的時(shí)間是很短的,幾微妙就能搞定。上下文切換本身對吞吐并多大影響, 重要的是,切換后引起的cpu 的 cache miss.
每次切換APP, 數(shù)據(jù)都要重新load一次。
Linux 會(huì)盡可能的在響應(yīng)與吞吐之間尋找平衡。比如在編譯linux的時(shí)候,會(huì)讓你選擇 kernal features - Preemption model.
搶占模型會(huì)影響linux的調(diào)度算法。
所以 ARM 的架構(gòu)都是big+LITTLE, 一個(gè)很猛CPU+ 多個(gè) 性能較差的 CPU, 那么可以把I/O型任務(wù)的調(diào)度 放在 LITTLE CPU上。需要計(jì)算的放在big上。
早期2.6 內(nèi)核將優(yōu)先級劃分了 0-139 bit的優(yōu)先級。數(shù)值越低,優(yōu)先級越高。0-99優(yōu)先級 都是 RT(即時(shí)響應(yīng))的 ,100-139都是非RT的,即normal。
調(diào)度的時(shí)候 看哪個(gè)bitmap 中的 優(yōu)先級上有任務(wù)ready??赡芏鄠€(gè)任務(wù)哦。
在普通優(yōu)先級線程調(diào)度中,高優(yōu)先級并不代表對低優(yōu)先級的絕對優(yōu)勢。會(huì)在不同優(yōu)先級進(jìn)行輪轉(zhuǎn)。
100 就是比101高,101也會(huì)比102高,但100 不會(huì)堵著101。
眾屌絲進(jìn)程在輪轉(zhuǎn)時(shí),優(yōu)先級高的:
初始設(shè)置nice值為0,linux 會(huì)探測 你是喜歡睡眠,還是干活。越喜歡睡,linux 越獎(jiǎng)勵(lì)你,優(yōu)先級上升(nice值減少)。越喜歡干活,優(yōu)先級下降(nice值增加)。所以一個(gè)進(jìn)程在linux中,干著干著 優(yōu)先級越低,睡著睡著 優(yōu)先級越高。
后期linux補(bǔ)丁中
紅黑樹,數(shù)據(jù)結(jié)構(gòu), 左邊節(jié)點(diǎn)小于右邊節(jié)點(diǎn)
同時(shí)兼顧了 CPU/IO 和 nice。
數(shù)值代表著 進(jìn)程運(yùn)行到目前為止的virtual runtime 時(shí)間。
(pyhsical runtime) / weight * 1024(系數(shù))。
優(yōu)先調(diào)度 節(jié)點(diǎn)值(vruntime)最小的線程。權(quán)重weight 其實(shí)有nice 來控制。
一個(gè)線程一旦被調(diào)度到,則物理運(yùn)行時(shí)間增加,vruntime增加,往左邊走。
weight的增加,也導(dǎo)致vruntime減小,往右邊走。
總之 CFS讓線程 從左滾到右,從右滾到左。即照顧了I/O(喜歡睡,分子小) 也 照顧了 nice值低(分母高).所以 由喜歡睡,nice值又低的線程,最容易被調(diào)度到。
自動(dòng)調(diào)整,無需向nice一樣做出獎(jiǎng)勵(lì)懲罰動(dòng)作,個(gè)人理解權(quán)重其實(shí)相當(dāng)于nice
但是 此時(shí) 來一個(gè) 0-99的線程,進(jìn)行RT調(diào)度,都可以瞬間秒殺你!因?yàn)槿思也皇瞧胀ǖ模荝T的!
一個(gè)多線程的進(jìn)程中,每個(gè)線程的調(diào)度的策略 如 fifo rr normal, 都可以不同。每一個(gè)的優(yōu)先級都可以不一樣。
實(shí)驗(yàn)舉例, 創(chuàng)建2個(gè)線程,同時(shí)開2個(gè):
運(yùn)行2次,創(chuàng)建兩個(gè)進(jìn)程
sudo renice -n -5(nice -5級別) -g(global), 會(huì)明顯看到 一個(gè)進(jìn)程的CPU占用率是另一個(gè)的 3倍。
為什么cpu都已經(jīng)達(dá)到200%,為什么系統(tǒng)不覺得卡呢?因?yàn)?,我們的線程在未設(shè)置優(yōu)先級時(shí),是normal調(diào)度模式,且是 CPU消耗型 調(diào)度級別其實(shí)不高。
利用chrt工具,可以將進(jìn)程 調(diào)整為 50 從normal的調(diào)度策略 升為RT (fifo)級別的調(diào)度策略,會(huì)出現(xiàn):
chrt , nice renice 的調(diào)度策略 都是以線程為單位的,以上 設(shè)置的將進(jìn)程下的所有線程進(jìn)行設(shè)置nice值
線程是調(diào)度單位,進(jìn)程不是,進(jìn)程是資源封裝單位!
兩個(gè)同樣死循環(huán)的normal優(yōu)先級線程,其中一個(gè)nice值降低,該線程的CPU 利用率就會(huì)比另一個(gè)CPU的利用率高。
導(dǎo)讀:本文將有助于你找出Redis 響應(yīng)延遲的問題所在。如果你正在經(jīng)歷響應(yīng)延遲問題,你或許能夠根據(jù)應(yīng)用程序的具體情況算出它的延遲響應(yīng)時(shí)間。
關(guān)鍵詞:Redis 數(shù)據(jù)庫延遲 響應(yīng)延遲
本文將有助于你找出Redis 響應(yīng)延遲的問題所在。
文中出現(xiàn)的延遲(latency)均指從客戶端發(fā)出一條命令到客戶端接受到該命令的反饋所用的最長響應(yīng)時(shí)間。Reids通常處理(命令的)時(shí)間非常的慢,大概在次微妙范圍內(nèi),但也有更長的情況出現(xiàn)。
計(jì)算延遲時(shí)間
如果你正在經(jīng)歷響應(yīng)延遲問題,你或許能夠根據(jù)應(yīng)用程序的具體情況算出它的延遲響應(yīng)時(shí)間,或者你的延遲問題非常明顯,宏觀看來,一目了然。不管怎樣吧,用redis-cli可以算出一臺(tái)Redis 服務(wù)器的到底延遲了多少毫秒。踹這句:
redis-cli --latency -h `host` -p `port`
網(wǎng)絡(luò)和通信引起的延遲
當(dāng)用戶連接到Redis通過TCP/IP連接或Unix域連接,千兆網(wǎng)絡(luò)的典型延遲大概200us,而Unix域socket可能低到30us。這完全基于你的網(wǎng)絡(luò)和系統(tǒng)硬件。在通信本身之上,系統(tǒng)增加了更多的延遲(線程調(diào)度,CPU緩存,NUMA替換等等)。系統(tǒng)引起的延遲在虛擬機(jī)環(huán)境遠(yuǎn)遠(yuǎn)高于在物理機(jī)器環(huán)境。
實(shí)際情況是即使Redis處理大多數(shù)命令在微秒之下,客戶機(jī)和服務(wù)器之間的交互也必然消耗系統(tǒng)相關(guān)的延遲。一個(gè)高效的客戶機(jī)因而試圖通過捆綁多個(gè)命令在一起的方式減少交互的次數(shù)。服務(wù)器和大多數(shù)客戶機(jī)支持這種方式。聚合命令象MSET/MGET也可以用作這個(gè)目的。從Redis 2.4版本起,很多命令對于所有的數(shù)據(jù)類型也支持可變參數(shù)。
這里有一些指導(dǎo):
如果你負(fù)擔(dān)的起,盡可能的使用物理機(jī)而不是虛擬機(jī)來做服務(wù)器
不要經(jīng)常的connect/disconnect與服務(wù)器的連接(尤其是對基于web的應(yīng)用),盡可能的延長與服務(wù)器連接的時(shí)間。
如果你的客戶端和服務(wù)器在同一臺(tái)主機(jī)上,則使用Unix域套接字
盡量使用聚合命令(MSET/MGET)或可變參數(shù)命令而不是pipelining
如果可以盡量使用pipelining而不是序列的往返命令。
針對不適合使用原始pipelining的情況,如某個(gè)命令的結(jié)果是后續(xù)命令的輸入,在以后的版本中redis提供了對服務(wù)器端的lua腳本的支持,實(shí)驗(yàn)分支版本現(xiàn)在已經(jīng)可以使用了。
在Linux上,你可以通過process placement(taskset)、cgroups、real-time priorities(chrt)、NUMA配置(numactl)或使用低延遲內(nèi)核的方式來獲取較低的延遲。請注意Redis 并不適合被綁到單個(gè)CPU核上。redis會(huì)在后臺(tái)創(chuàng)建一些非常消耗CPU的進(jìn)程,如bgsave和AOF重寫,這些任務(wù)是絕對不能和主事件循環(huán)進(jìn)程放在一個(gè)CPU核上的。大多數(shù)情況下上述的優(yōu)化方法是不需要的,除非你確實(shí)需要并且你對優(yōu)化方法很熟悉的情況下再使用上述方法。
Redis的單線程屬性
Redis 使用了單線程的設(shè)計(jì), 意味著單線程服務(wù)于所有的客戶端請求,使用一種復(fù)用的技術(shù)。這種情況下redis可以在任何時(shí)候處理單個(gè)請求, 所以所有的請求是順序處理的。這和Node.js的工作方式很像, 所有的產(chǎn)出通常不會(huì)有慢的感覺,因?yàn)樘幚韱蝹€(gè)請求的時(shí)間非常短,但是最重要的是這些產(chǎn)品被設(shè)計(jì)為非阻塞系統(tǒng)調(diào)用,比如從套接字中讀取或?qū)懭霐?shù)據(jù)。
我提到過Redis從2.4版本后幾乎是單線程的,我們使用線程在后臺(tái)運(yùn)行一些效率低下的I/O操作, 主要關(guān)系到硬盤I/O,但是這不改變Redis使用單線程處理所有請求的事實(shí)。
低效操作產(chǎn)生的延遲
單線程的一個(gè)結(jié)果是,當(dāng)一個(gè)請求執(zhí)行得很慢,其他的客戶端調(diào)用就必須等待這個(gè)請求執(zhí)行完畢。當(dāng)執(zhí)行GET、SET或者LPUSH 命令的時(shí)候這不是個(gè)問題,因?yàn)檫@些操作可在很短的常數(shù)時(shí)間內(nèi)完成。然而,對于多個(gè)元素的操作,像SORT,LREM, SUNION 這些,做兩個(gè)大數(shù)據(jù)集的交叉要花掉很長的時(shí)間。文檔中提到了所有操作的算法復(fù)雜性。 在使用一個(gè)你不熟悉的命令之前系統(tǒng)的檢查它會(huì)是一個(gè)好辦法。
如果你對延遲有要求,那么就不要執(zhí)行涉及多個(gè)元素的慢操作,你可以使用Redis的replication功能,把這類慢操作全都放到replica上執(zhí)行。可以用Redis 的Slow Log來監(jiān)控慢操作。此外,你可以用你喜歡的進(jìn)程監(jiān)控程序(top, htop, prstat, 等...)來快速查看Redis進(jìn)程的CPU使用率。如果traffic不高而CPU占用很高,八成說明有慢操作。
延遲由fork產(chǎn)生
Redis不論是為了在后臺(tái)生成一個(gè)RDB文件,還是為了當(dāng)AOF持久化方案被開啟時(shí)重寫Ap
pend Only文件,都會(huì)在后臺(tái)fork出一個(gè)進(jìn)程。fork操作(在主線程中被執(zhí)行)本身會(huì)引發(fā)延遲。在大多數(shù)的類unix操作系統(tǒng)中,fork是一個(gè)很消耗的操作,因?yàn)樗鼱可娴綇?fù)制很多與進(jìn)程相關(guān)的對象。而這對于分頁表與虛擬內(nèi)存機(jī)制關(guān)聯(lián)的系統(tǒng)尤為明顯。
對于運(yùn)行在一個(gè)linux/AMD64系統(tǒng)上的實(shí)例來說,內(nèi)存會(huì)按照每頁4KB的大小分頁。為了實(shí)現(xiàn)虛擬地址到物理地址的轉(zhuǎn)換,每一個(gè)進(jìn)程將會(huì)存儲(chǔ)一個(gè)分頁表(樹狀形式表現(xiàn)),分頁表將至少包含一個(gè)指向該進(jìn)程地址空間的指針。所以一個(gè)空間大小為24GB的redis實(shí)例,需要的分頁表大小為 24GB/4KB*8 = 48MB。當(dāng)一個(gè)后臺(tái)的save命令執(zhí)行時(shí),實(shí)例會(huì)啟動(dòng)新的線程去申請和拷貝48MB的內(nèi)存空間。這將消耗一些時(shí)間和CPU資源,尤其是在虛擬機(jī)上申請和初始化大塊內(nèi)存空間時(shí),消耗更加明顯。
在不同系統(tǒng)中的Fork時(shí)間
除了Xen系統(tǒng)外,現(xiàn)代的硬件都可以快速完美的復(fù)制頁表。Xen系統(tǒng)的問題不是特定的虛擬化,而是特定的Xen.例如使用VMware或者Virutal Box不會(huì)導(dǎo)致較慢的fork時(shí)間。下面的列表比較了不同Redis實(shí)例的fork時(shí)間。數(shù)據(jù)包含正在執(zhí)行的BGSAVE,并通過INFO指令查看thelatest_fork_usecfiled。
Linux beefy VM on VMware 6.0GB RSS forked 77 微秒 (每GB 12.8 微秒 ).
Linux running on physical machine (Unknown HW) 6.1GB RSS forked 80 微秒(每GB 13.1微秒)
Linux running on physical machine (Xeon @ 2.27Ghz) 6.9GB RSS forked into 62 微秒 (每GB 9 微秒).
Linux VM on 6sync (KVM) 360 MB RSS forked in 8.2 微秒 (每GB 23.3 微秒).
Linux VM on EC2 (Xen) 6.1GB RSS forked in 1460 微秒 (每GB 239.3 微秒).
Linux VM on Linode (Xen) 0.9GBRSS forked into 382 微秒 (每GB 424 微秒).
你能看到運(yùn)行在Xen上的VM的Redis性能相差了一到兩個(gè)數(shù)量級。我們相信這是Xen系統(tǒng)的一個(gè)驗(yàn)證問題,我們希望這個(gè)問題能盡快處理。
swapping (操作系統(tǒng)分頁)引起的延遲
Linux (以及其他一些操作系統(tǒng)) 可以把內(nèi)存頁存儲(chǔ)在硬盤上,反之也能將存儲(chǔ)在硬盤上的內(nèi)存頁再加載進(jìn)內(nèi)存,這種機(jī)制使得內(nèi)存能夠得到更有效的利用。如果內(nèi)存頁被系統(tǒng)移到了swap文件里,而這個(gè)內(nèi)存頁中的數(shù)據(jù)恰好又被redis用到了(例如要訪問某個(gè)存儲(chǔ)在內(nèi)存頁中的key),系統(tǒng)就會(huì)暫停redis進(jìn)程直到把需要的頁數(shù)據(jù)重新加載進(jìn)內(nèi)存。這個(gè)操作因?yàn)闋可娴诫S機(jī)I/O,所以很慢,會(huì)導(dǎo)致無法預(yù)料的延遲。
系統(tǒng)之所以要在內(nèi)存和硬盤之間置換redis頁數(shù)據(jù)主要因?yàn)橐韵氯齻€(gè)原因:
系統(tǒng)總是要應(yīng)對內(nèi)存不足的壓力,因?yàn)槊總€(gè)運(yùn)行的進(jìn)程都想申請更多的物理內(nèi)存,而這些申請的內(nèi)存的數(shù)量往往超過了實(shí)際擁有的內(nèi)存。簡單來說就是redis使用的內(nèi)存總是比可用的內(nèi)存數(shù)量更多。
redis實(shí)例的數(shù)據(jù),或者部分?jǐn)?shù)據(jù)可能就不會(huì)被客戶端訪問,所以系統(tǒng)可以把這部分閑置的數(shù)據(jù)置換到硬盤上。需要把所有數(shù)據(jù)都保存在內(nèi)存中的情況是非常罕見的。
一些進(jìn)程會(huì)產(chǎn)生大量的讀寫I/O。因?yàn)槲募ǔ6加芯彺?,這往往會(huì)導(dǎo)致文件緩存不斷增加,然后產(chǎn)生交換(swap)。請注意,redis RDB和AOF后臺(tái)線程都會(huì)產(chǎn)生大量文件。
所幸Linux提供了很好的工具來診斷這個(gè)問題,所以當(dāng)延遲疑似是swap引起的,最簡單的辦法就是使用Linux提供的工具去確診。
首先要做的是檢查swap到硬盤上的redis內(nèi)存的數(shù)量,為實(shí)現(xiàn)這個(gè)目的要知道redis實(shí)例的進(jìn)程id:
$ redis-cli info | grep process_id
process_id:5454
進(jìn)入進(jìn)程目錄:
$ cd /proc/5454在這里你會(huì)發(fā)現(xiàn)一個(gè)名為smaps 的文件,它描述了redis進(jìn)程的內(nèi)存布局 (假定你使用的是Linux 2.6.16或者更新的版本)。這個(gè)文件包括了很多進(jìn)程所使用內(nèi)存的細(xì)節(jié)信息,其中有一項(xiàng)叫做Swap的正是我們所關(guān)心的。不過僅看這一項(xiàng)是不夠的,因?yàn)閟maps文件包括有redis進(jìn)程的多個(gè)不同的的內(nèi)存映射區(qū)域的使用情況(進(jìn)程的內(nèi)存布局遠(yuǎn)不是線性排列那么簡單)。
從我們對所有進(jìn)程的內(nèi)存交換情況感興趣以來,我們首先要做的事情是使用grep命令顯示進(jìn)程的smaps文件
$ cat smaps | grep 'Swap:'
Swap: 0 kB
Swap: 0 kB
Swap: 0 kB
Swap: 0 kB
Swap: 0 kB
Swap: 12 kB
Swap: 156 kB
Swap: 8 kB
Swap: 0 kB
Swap: 0 kB
Swap: 0 kB
Swap: 0 kB
Swap: 0 kB
Swap: 0 kB
Swap: 0 kB
Swap: 0 kB
Swap: 0 kB
Swap: 4 kB
Swap: 0 kB
Swap: 0 kB
Swap: 4 kB
Swap: 0 kB
Swap: 0 kB
Swap: 4 kB
Swap: 4 kB
Swap: 0 kB
Swap: 0 kB
Swap: 0 kB
Swap: 0 kB
Swap: 0 kB假如所有的數(shù)據(jù)顯示為0kb或者某些數(shù)據(jù)偶爾顯示為4kb,表示當(dāng)前一切正常。實(shí)際上我們的例子是一個(gè)真實(shí)的運(yùn)行著Redis并每秒為數(shù)百的用戶提供服務(wù)的網(wǎng)站,會(huì)顯示更多的交換頁。為了研究是否存在一個(gè)嚴(yán)重的問題,我們改變命令打印出分配的內(nèi)存尺寸
$ cat smaps | egrep '^(Swap|Size)'
Size: 316 kB
Swap: 0 kB
Size: 4 kB
Swap: 0 kB
Size: 8 kB
Swap: 0 kB
Size: 40 kB
Swap: 0 kB
Size: 132 kB
Swap: 0 kB
Size: 720896 kB
Swap: 12 kB
Size: 4096 kB
Swap: 156 kB
Size: 4096 kB
Swap: 8 kB
Size: 4096 kB
Swap: 0 kB
Size: 4 kB
Swap: 0 kB
Size: 1272 kB
Swap: 0 kB
Size: 8 kB
Swap: 0 kB
Size: 4 kB
Swap: 0 kB
Size: 16 kB
Swap: 0 kB
Size: 84 kB
Swap: 0 kB
Size: 4 kB
Swap: 0 kB
Size: 4 kB
Swap: 0 kB
Size: 8 kB
Swap: 4 kB
Size: 8 kB
Swap: 0 kB
Size: 4 kB
Swap: 0 kB
Size: 4 kB
Swap: 4 kB
Size: 144 kB
Swap: 0 kB
Size: 4 kB
Swap: 0 kB
Size: 4 kB
Swap: 4 kB
Size: 12 kB
Swap: 4 kB
Size: 108 kB
Swap: 0 kB
Size: 4 kB
Swap: 0 kB
Size: 4 kB
Swap: 0 kB
Size: 272 kB
Swap: 0 kB
Size: 4 kB
Swap: 0 kB
在輸出信息中,你能看到有一個(gè)720896kb的內(nèi)存分配(有12kb的交換)還有一個(gè)156kb的交換是另一個(gè)進(jìn)程的?;旧衔覀兊膬?nèi)存只會(huì)有很小的內(nèi)存交換,因此不會(huì)產(chǎn)生任何的問題.
假如進(jìn)程的內(nèi)存有相當(dāng)部分花在了swap上,那么你的延遲可能就與swap有關(guān)。假如redis出現(xiàn)這種情況那么可以用vmstat 命令來驗(yàn)證一下猜測:
$ vmstat 1
procs -----------memory---------- ---swap-- -----io---- -system-- ----cpu----
r b swpd free buff cache si so bi bo in cs us sy id wa
0 0 3980 697932 147180 1406456 0 0 2 2 2 0 4 4 91 0
0 0 3980 697428 147180 1406580 0 0 0 0 19088 16104 9 6 84 0
0 0 3980 697296 147180 1406616 0 0 0 28 18936 16193 7 6 87 0
0 0 3980 697048 147180 1406640 0 0 0 0 18613 15987 6 6 88 0
2 0 3980 696924 147180 1406656 0 0 0 0 18744 16299 6 5 88 0
0 0 3980 697048 147180 1406688 0 0 0 4 18520 15974 6 6 88 0
輸出中我們最感興趣的兩行是si 和 so,這兩行分別統(tǒng)計(jì)了從swap文件恢復(fù)到內(nèi)存的數(shù)量和swap到文件的內(nèi)存數(shù)量。如果在這兩行發(fā)現(xiàn)了非0值那么就說明系統(tǒng)正在進(jìn)行swap。
最后,可以用iostat命令來查看系統(tǒng)的全局I/O行為。
$ iostat -xk 1
avg-cpu: %user %nice %system %iowait %steal %idle
13.55 0.04 2.92 0.53 0.00 82.95
Device: rrqm/s wrqm/s r/s w/s rkB/s wkB/s avgrq-sz avgqu-sz await svctm %util
sda 0.77 0.00 0.01 0.00 0.40 0.00 73.65 0.00 3.62 2.58 0.00
sdb 1.27 4.75 0.82 3.54 38.00 32.32 32.19 0.11 24.80 4.24 1.85
如果確認(rèn)延遲是由于swap引起的,那么就需要減小系統(tǒng)的內(nèi)存壓力,要么給機(jī)器增加內(nèi)存,要么不要在同一個(gè)機(jī)器上運(yùn)行其他消耗內(nèi)存的程序。
轉(zhuǎn)載,僅供參考,祝你愉快,滿意請采納。
在 Linux 中,線程是由進(jìn)程來實(shí)現(xiàn)的,可以認(rèn)為線程就是一個(gè)輕量級的進(jìn)程,因此,線程調(diào)度是按照進(jìn)程調(diào)度的方式來進(jìn)行的。這樣設(shè)計(jì),線程調(diào)度流程可以直接復(fù)用進(jìn)程調(diào)度流程,沒必要再設(shè)計(jì)一個(gè)進(jìn)程內(nèi)的線程調(diào)度器了。
在 Linux 中,進(jìn)程調(diào)度器是基于進(jìn)程的調(diào)度策略與調(diào)度優(yōu)先級來決定調(diào)度哪個(gè)進(jìn)程運(yùn)行。
調(diào)度策略主要包括:
調(diào)度優(yōu)先級的范圍是 0~99,數(shù)值越大,表示優(yōu)先級越高。
其中,SCHED_OTHER、SCHED_IDLE、SCHED_BACH 為非實(shí)時(shí)調(diào)度策略,其調(diào)度優(yōu)先級為 0。而 SCHED_FIFO、SCHED_RR 是實(shí)時(shí)調(diào)度策略,其調(diào)度優(yōu)先級范圍為 1~99。
實(shí)時(shí)調(diào)度策略的進(jìn)程總是比非實(shí)時(shí)調(diào)度策略的進(jìn)程優(yōu)先級高。
在 Linux 內(nèi)部實(shí)現(xiàn)中,調(diào)度器會(huì)為每個(gè)可能的調(diào)度優(yōu)先級維護(hù)一個(gè)可運(yùn)行的進(jìn)程列表,以最高優(yōu)先級列表頭部的進(jìn)程作為下一次調(diào)度的進(jìn)程,所有的調(diào)度都是搶占式的,如果一個(gè)具有更高調(diào)度優(yōu)先級的進(jìn)程轉(zhuǎn)換為可運(yùn)行狀態(tài),那么當(dāng)前運(yùn)行的進(jìn)程將被強(qiáng)制進(jìn)入其等待的隊(duì)列中。
SCHED_OTHER
該調(diào)度策略是默認(rèn)的 Linux 分時(shí)調(diào)度策略,該調(diào)度策略為非實(shí)時(shí)的,其調(diào)度優(yōu)先級總是為 0。
對于該調(diào)度策略類型的進(jìn)程,調(diào)度器是基于動(dòng)態(tài)優(yōu)先級來調(diào)度的。動(dòng)態(tài)優(yōu)先級跟屬性 nice 有關(guān),nice 的值會(huì)隨著進(jìn)程的運(yùn)行時(shí)間而動(dòng)態(tài)改變,以確保所有具有 SCHED_OTHER 策略的進(jìn)程公平地得到調(diào)度。
在 Linux 中,nice 的值范圍為-20 ~ +19,默認(rèn)值為 0。nice 值越大,則優(yōu)先級越低,因此相對較低 nice 值的進(jìn)程可以獲得更多的處理器時(shí)間。
通過命令 ps -el 查看系統(tǒng)中的進(jìn)程列表,其中 NI 列就是進(jìn)程對應(yīng)的 nice 值。
使用 top 命令,看到的 NI 列也是進(jìn)程的 nice 值。
調(diào)整 nice 值,可以通過 shell 命令 nice ,該命令可以按照指定的 nice 值運(yùn)行 cmd ,命令的幫助信息為:
重新調(diào)整已運(yùn)行進(jìn)程的 nice 值,可通過 renice 命令實(shí)現(xiàn),命令的幫助信息為:
另外,可以執(zhí)行 top 命令,輸入 r ,根據(jù)提示輸入進(jìn)程的 pid ,再輸入 nice 數(shù)值,也可以調(diào)整進(jìn)程的 nice 值。
SCHED_FIFO
該調(diào)度策略為先入先出調(diào)度策略,簡單概括,就是一旦進(jìn)程占用了 CPU,則一直運(yùn)行,直到有更高優(yōu)先級的任務(wù)搶占,或者進(jìn)程自己放棄占用 CPU。
SCHED_RR
該調(diào)度策略為時(shí)間片輪轉(zhuǎn)調(diào)度策略,該調(diào)度策略是基于 SCHED_FIFO 策略的演進(jìn),其在每個(gè)進(jìn)程上增加一個(gè)時(shí)間片限制,當(dāng)時(shí)間片使用完成后,調(diào)度器將該進(jìn)程置于隊(duì)列的尾端,放在尾端保證了所有具有相同調(diào)度優(yōu)先級的進(jìn)程的調(diào)度公平。
使用 top 命令,如果 PR 列的值為 RT ,則說明該進(jìn)程采用的是實(shí)時(shí)調(diào)度策略,其調(diào)度策略為 SCHED_FIFO 或者 SCHED_RR,而對于非實(shí)時(shí)調(diào)度策略的進(jìn)程,該列的值為 NI + 20 。
可以通過命令 ps -eo state,uid,pid,ppid,rtprio,time,comm 來查看進(jìn)程對應(yīng)的實(shí)時(shí)優(yōu)先級,實(shí)時(shí)優(yōu)先級位于 RTPRIO 列下,如果進(jìn)程對應(yīng)的列顯示為 - ,說明該進(jìn)程不是實(shí)時(shí)進(jìn)程。
chrt 命令可以用來很簡單地更改進(jìn)程的調(diào)度策略與調(diào)度優(yōu)先級。在 Linux 下查看 chrt 命令的幫助信息:
比如,獲取某個(gè)進(jìn)程的調(diào)度策略,使用如下命令:
在比如,設(shè)置某個(gè)進(jìn)程的調(diào)度策略為 SCHED_FIFO,調(diào)度優(yōu)先級為 70,使用如下命令: