調度策略值得是大家都在ready時,並且CPU已經被調度時,決定誰來運行,誰來被調度。
兩者之間有一定矛盾。
響應的優化,意味著高優先順序會搶占優先順序,會花時間在上下文切換,會影響吞吐。
上下文切換的時間是很短的,幾微妙就能搞定。上下文切換本身對吞吐並多大影響, 重要的是,切換後引起的cpu 的 cache miss.
每次切換APP, 數據都要重新load一次。
Linux 會盡可能的在響應與吞吐之間尋找平衡。比如在編譯linux的時候,會讓你選擇 kernal features -> Preemption model.
搶占模型會影響linux的調度演算法。
所以 ARM 的架構都是big+LITTLE, 一個很猛CPU+ 多個 性能較差的 CPU, 那麼可以把I/O型任務的調度 放在 LITTLE CPU上。需要計算的放在big上。
早期2.6 內核將優先順序劃分了 0-139 bit的優先順序。數值越低,優先順序越高。0-99優先順序 都是 RT(即時響應)的 ,100-139都是非RT的,即normal。
調度的時候 看哪個bitmap 中的 優先順序上有任務ready。可能多個任務哦。
在普通優先順序線程調度中,高優先順序並不代表對低優先順序的絕對優勢。會在不同優先順序進行輪轉。
100 就是比101高,101也會比102高,但100 不會堵著101。
眾屌絲進程在輪轉時,優先順序高的:
初始設置nice值為0,linux 會探測 你是喜歡睡眠,還是幹活。越喜歡睡,linux 越獎勵你,優先順序上升(nice值減少)。越喜歡幹活,優先順序下降(nice值增加)。所以一個進程在linux中,干著干著 優先順序越低,睡著睡著 優先順序越高。
後期linux補丁中
紅黑樹,數據結構, 左邊節點小於右邊節點
同時兼顧了 CPU/IO 和 nice。
數值代表著 進程運行到目前為止的virtual runtime 時間。
(pyhsical runtime) / weight * 1024(系數)。
優先調度 節點值(vruntime)最小的線程。權重weight 其實有nice 來控制。
一個線程一旦被調度到,則物理運行時間增加,vruntime增加,往左邊走。
weight的增加,也導致vruntime減小,往右邊走。
總之 CFS讓線程 從左滾到右,從右滾到左。即照顧了I/O(喜歡睡,分子小) 也 照顧了 nice值低(分母高).所以 由喜歡睡,nice值又低的線程,最容易被調度到。
自動調整,無需向nice一樣做出獎勵懲罰動作,個人理解權重其實相當於nice
但是 此時 來一個 0-99的線程,進行RT調度,都可以瞬間秒殺你!因為人家不是普通的,是RT的!
一個多線程的進程中,每個線程的調度的策略 如 fifo rr normal, 都可以不同。每一個的優先順序都可以不一樣。
實驗舉例, 創建2個線程,同時開2個:
運行2次,創建兩個進程
sudo renice -n -5(nice -5級別) -g(global), 會明顯看到 一個進程的CPU佔用率是另一個的 3倍。
為什麼cpu都已經達到200%,為什麼系統不覺得卡呢?因為,我們的線程在未設置優先順序時,是normal調度模式,且是 CPU消耗型 調度級別其實不高。
利用chrt工具,可以將進程 調整為 50 從normal的調度策略 升為RT (fifo)級別的調度策略,會出現:
chrt , nice renice 的調度策略 都是以線程為單位的,以上 設置的將進程下的所有線程進行設置nice值
線程是調度單位,進程不是,進程是資源封裝單位!
兩個同樣死循環的normal優先順序線程,其中一個nice值降低,該線程的CPU 利用率就會比另一個CPU的利用率高。
② 為什麼Linux CFS調度器沒有帶來驚艷的碾壓效果| CSDN博文精選
任何領域,革命性的碾壓式推陳出新並不是沒有,但是概率極低,人們普遍的狂妄在於,總是認為自己所置身的環境正在發生著某種碾壓式的變革,但其實,最終大概率不過是一場平庸。
作者 | dog250
責編 | 劉靜
出品 | CSDN博客
但凡懂Linux內核的,都知道Linux內核的CFS進程調度演算法,無論是從2.6.23將其初引入時的論文,還是各類源碼分析,文章,以及Linux內核專門的圖書,都給人這樣一種感覺,即 CFS調度器是革命性的,它將徹底改變進程調度演算法。 預期中,人們期待它會帶來令人驚艷的效果。
然而這是錯覺。
人們希望CFS速勝,但是分析來分析去, 卻只是在某些方面比O(1)調度器稍微好一點點 。甚至在某些方面比不上古老的4.4BSD調度器。可是人們卻依然對其趨之若鶩,特別是源碼分析,汗牛塞屋!
為什麼CFS對別的調度演算法沒有帶來碾壓的效果呢?
首先,在真實世界,碾壓是不存在的,人與人,事與事既然被放在了同一個重量級梯隊比較,其之間的差別沒有想像的那麼大,根本就不在誰碾壓誰。不能被小說電視劇電影蒙蔽了,此外,徐曉冬大擺拳暴打雷雷也不算數,因為他們本就不是一個梯隊。
任何領域,革命性的碾壓式推陳出新並不是沒有,但是概率極低,人們普遍的狂妄在於,總是認為自己所置身的環境正在發生著某種碾壓式的變革,但其實,最終大概率不過是一場平庸。
最終就出現了角力,僵持。
其次,我們應該看到,CFS調度器聲稱它會給互動式進程帶來福音,在這方面CFS確實比O(1)做得好,但是驚艷的效果來自於粉絲的認同。Linux系統交互進程本來就不多,Linux更多地被裝在伺服器,而在伺服器看來,吞吐是要比交互響應更加重要的。
那麼以交互為主的Android系統呢?我們知道,Android也是採用了CFS調度器,也有一些事BFS,為什麼同樣沒有帶來驚艷的效果呢?
我承認,2008年前後出現CFS時還沒有Android,等到Android出現時,其採用的Linux內核已經默認了CFS調度器,我們看下Android版本,Linux內核版本以及發行時間的關系:
Linux內核在2.6.23就採用了CFS調度器。所以一個原因就是沒有比較。Android系統上,CFS沒有機會和O(1)做比較。
另外,即便回移一個O(1)調度器到Android系統去和CFS做AB,在我看來,CFS同樣不會驚艷,原因很簡單,Android系統幾乎都是交互進程,卻前台進程永遠只有一個,你幾乎感受不到進程的切換卡頓,換句話說,即便CFS對待互動式進程比O(1)好太多,你也感受不到,因為對於手機,平板而言,你切換 APP 的時間遠遠大於進程切換的時間粒度。
那麼,CFS到底好在哪裡?
簡單點說,CFS的意義在於, 在一個混雜著大量計算型進程和IO交互進程的系統中,CFS調度器對待IO交互進程要比O(1)調度器更加友善和公平 。理解這一點至關重要。
其實,CFS調度器的理念非常古老,就說在業界,CFS的思想早就被應用在了磁碟IO調度,數據包調度等領域,甚至最最古老的SRV3以及4.3BSD UNIX系統的進程調度中早就有了CFS的身影,可以說,Linux只是 使用CFS調度器 ,而不是 設計了CFS調度器 !
就以4.3BSD調度器為例,我們看一下其調度原理。
4.3BSD採用了1秒搶占制,每間隔1秒,會對整個系統進程進行優先順序排序,然後找到優先順序最高的投入運行,非常簡單的一個思想,現在看看它是如何計算優先順序的。
首先,每一個進程j均擁有一個CPU滴答的度量值Cj,每一個時鍾滴答,當前在運行的進程的CPU度量值C會遞增:
當一個1秒的時間區間ii過去之後,Cj被重置,該進程jj的優先順序採用下面的公式計算:
可以計算,在一個足夠長的時間段內,兩個進程運行的總時間比例,將和它們的Base_PrioBase_Prio優先順序的比例相等。
4.3BSD的優先順序公平調度是CPU滴答驅動的。
現在看Linux的CFS,CFS採用隨時搶占制。每一個進程j均攜帶一個 虛擬時鍾VCj ,每一個時鍾滴答,當前進程k的VCk會重新計算,同時調度器選擇VC最小的進程運行,計算方法非常簡單:
可見, Linux的CFS簡直就是4.3BSD進程調度的自驅無級變速版本!
如果你想了解CFS的精髓,上面的就是了。換成語言描述,CFS的精髓就是 「 n個進程的系統,任意長的時間周期TT,每一個進程運行T/n的時間! 」
當然,在現實和實現中,會有80%的代碼處理20%的剩餘問題,比如如何獎勵睡眠太久的進程等等,但是這些都不是精髓。
綜上,我們總結了:
所以無論從概念還是從效果,Linux CFS調度器均沒有帶來令人眼前一亮的哇塞效果。但是還缺點什麼。嗯,技術上的解釋。
分析和解釋任何一個機制之前,必然要先問,這個機制的目標是什麼,它要解決什麼問題,這樣才有意義。而不能僅僅是明白了它是怎麼工作的。
那麼Linux CFS調度器被採用,它的目標是解決什麼問題的呢?它肯定是針對O(1)演算法的一個問題而被引入並取代O(1),該問題也許並非什麼臭名昭著,但是確實是一枚釘子,必須拔除。
O(1)調度器的本質問題在於 進程的優先順序和進程可運行的時間片進行了強映射!
也就是說,給定一個進程優先順序,就會計算出一個時間片與之對應,我們忽略獎懲相關的動態優先順序,看一下原始O(1)演算法中一個進程時間片的計算:
直觀點顯示:
針對上述問題,2.6內核的O(1)O(1)引入了雙斜率來解決:
直觀圖示如下:
貌似問題解決了,但是如果單單揪住上圖的某一個優先順序子區間來看,還是會有問題,這就是相對優先順序的問題。我們看到,高優先順序的時間片是緩慢增減的,而低優先順序的時間片卻是陡然增減,同樣都是相差同樣優先順序的進程,其優先順序分布影響了它們的時間片分配。
本來是治瘸子,結果腿好了,但是胳臂壞了。
本質上來講,這都源自於下面兩個原因:
固定的優先順序映射到固定的時間片。
相對優先順序和絕對優先順序混雜。
那麼這個問題如何解決?
優先順序和時間片本來就是兩個概念,二者中間還得有個變數溝通才可以。優先順序高只是說明該進程能運行的久一些,但是到底久多少,並不是僅僅優先順序就能決定的,還要綜合考慮,換句話距離來說,如果只有一個進程,那麼即便它優先順序再低,它也可以永久運行,如果系統中有很多的進程,即便再高優先順序的進程也要讓出一些時間給其它進程。
所以,考慮到系統中總體的進程情況,將優先順序轉換為權重,將時間片轉換為份額,CFS就是了。最終的坐標系應該是 權重佔比/時間片 坐標系而不是 權重(或者優先順序)/時間片 。應該是這個平滑的樣子:
看來,Linux CFS只是為了解決O(1)O(1)中一個 「靜態優先順序/時間片映射」 問題的,那麼可想而知,它又能帶來什麼驚艷效果呢?這里還有個「但是」,這個O(1)O(1)調度器的問題其實在計算密集型的守護進程看來,並不是問題,反而是好事,畢竟高優先順序進程可以 無條件持續運行很久而不切換 。這對於吞吐率的提高,cache利用都是有好處的。無非也就侵擾了交互進程唄,又有何妨。
當然,使用調優CFS的時候,難免也要遇到IO睡眠獎懲等剩餘的事情去設計一些trick演算法,這破費精力。
對了,還要設置你的內核為HZ1000哦,這樣更能體現CFS的平滑性,就像它宣稱的那樣。我難以想像,出了Ubuntu,Suse等花哨的桌面發行版之外,還有哪個Linux需要打開HZ1000,伺服器用HZ250不挺好嗎?
關於調度的話題基本就說完了,但是在進入下一步固有的噴子環節之前,還有兩點要強調:
在CPU核數越來越多的時代,人們更應該關心 把進程調度到哪裡CPU核上 而不是 某個CPU核要運行哪個進程 。
單核時代一路走過來的Linux,發展迅猛,這無可厚非,但是成就一個操作系統內核的並不單單是技術,還有別的。這些當然程序員們很不愛聽,程序員最煩非技術方面的東西了,程序員跟誰都比寫代碼,程序員特別喜歡噴領導不會寫代碼雲雲。
Linux在純技術方面並不優秀,Linux總體上優秀的原因是因為有一群非代碼不明志的程序員在讓它變得越來越優秀,另一方面還要歸功於開源和社區。Linux的學習門檻極低,如果一個公司能不費吹灰之力招聘到一個Linux程序員的話,那它幹嘛還要費勁九牛二虎之力去招聘什麼高端的BSD程序員呢?最終的結果就是,Linux用的人極多,想換也換不掉了。
但無論如何也沒法彌補Linux內核上的一些原則性錯誤。
Linux內核還是以原始的主線為base,以講Linux內核的書為例,經典的Robert Love的《Linux內核設計與實現》,以及《深入理解Linux內核》,在講進程調度的時候,關於多核負載均衡的筆墨都是少之又少甚至沒有,如此經典的著作把很多同好引向了那萬劫不復的代碼深淵。於是乎,鋪天蓋地的CFS源碼分析紛至沓來。
但其實,拋開這么一個再普通不過的Linux內核,現代操作系統進入了多核時代,其核心正是在cache利用上的革新,帶來的轉變就是進程調度和內存管理的革新。review一下Linux內核源碼,這些改變早就已經表現了出來。
可悲的是,關於Linux內核的經典書籍卻再也沒有更新,所有的從傳統學校出來的喜歡看書學習的,依然是抱著10年前的大部頭在啃。
http :// www. ece.ubc.ca/~sasha/papers/eurosys16-final29.pdf
浙江溫州皮鞋濕,下雨進水不會胖。
作者:CSDN博主「dog250」,本文首發於作者CSDN博客https://blog.csdn.net/dog250/article/details/957298 30 。
【END】
③ 一文讀懂Linux任務間調度原理和整個執行過程
在前文中,我們分析了內核中進程和線程的統一結構體task_struct,並分析進程、線程的創建和派生的過程。在本文中,我們會對任務間調度進行詳細剖析,了解其原理和整個執行過程。由此,進程、線程部分的大體框架就算是介紹完了。本節主要分為三個部分:Linux內核中常見的調度策略,調度的基本結構體以及調度發生的整個流程。下面將詳細展開說明。
Linux 作為一個多任務操作系統,將每個 CPU 的時間劃分為很短的時間片,再通過調度器輪流分配給各個任務使用,因此造成多任務同時運行的錯覺。為了維護 CPU 時間,Linux 通過事先定義的節拍率(內核中表示為 HZ),觸發時間中斷,並使用全局變數 Jiffies 記錄了開機以來的節拍數。每發生一次時間中斷,Jiffies 的值就加 1。節拍率 HZ 是內核的可配選項,可以設置為 100、250、1000 等。不同的系統可能設置不同的數值,可以通過查詢 /boot/config 內核選項來查看它的配置值。
Linux的調度策略主要分為實時任務和普通任務。實時任務需求盡快返回結果,而普通任務則沒有較高的要求。在前文中我們提到了task_struct中調度策略相應的變數為policy,調度優先順序有prio, static_prio, normal_prio, rt_priority幾個。優先順序其實就是一個數值,對於實時進程來說,優先順序的范圍是 0 99;對於普通進程,優先順序的范圍是 100 139。數值越小,優先順序越高。
實時調度策略主要包括以下幾種
普通調度策略主要包括以下幾種:
首先,我們需要一個結構體去執行調度策略,即sched_class。該類有幾種實現方式
普通任務調度實體源碼如下,這裡麵包含了 vruntime 和權重 load_weight,以及對於運行時間的統計。
在調度時,多個任務調度實體會首先區分是實時任務還是普通任務,然後通過以時間為順序的紅黑樹結構組合起來,vruntime 最小的在樹的左側,vruntime最多的在樹的右側。以CFS策略為例,則會選擇紅黑樹最左邊的葉子節點作為下一個將獲得 CPU 的任務。而這顆紅黑樹,我們稱之為運行時隊列(run queue),即struct rq。
其中包含結構體cfs_rq,其定義如下,主要是CFS調度相關的結構體,主要有權值相關變數、vruntime相關變數以及紅黑樹指針,其中結構體rb_root_cached即為紅黑樹的節點
對結構體dl_rq有類似的定義,運行隊列由紅黑樹結構體構成,並按照deadline策略進行管理
對於實施隊列相應的rt_rq則有所不同,並沒有用紅黑樹實現。
下面再看看調度類sched_class,該類以函數指針的形式定義了諸多隊列操作,如
調度類分為下面幾種:
隊列操作中函數指針指向不同策略隊列的實際執行函數函數,在linux/kernel/sched/目錄下,fair.c、idle.c、rt.c等文件對不同類型的策略實現了不同的函數,如fair.c中定義了
以選擇下一個任務為例,CFS對應的是pick_next_task_fair,而rt_rq對應的則是pick_next_task_rt,等等。
由此,我們來總結一下:
有了上述的基本策略和基本調度結構體,我們可以形成大致的骨架,下面就是需要核心的調度流程將其拼湊成一個整體,實現調度系統。調度分為兩種,主動調度和搶占式調度。
說到調用,逃不過核心函數schele()。其中sched_submit_work()函數完成當前任務的收尾工作,以避免出現如死鎖或者IO中斷等情況。之後首先禁止搶占式調度的發生,然後調用__schele()函數完成調度,之後重新打開搶占式調度,如果需要重新調度則會一直重復該過程,否則結束函數。
而__schele()函數則是實際的核心調度函數,該函數主要操作包括選取下一進程和進行上下文切換,而上下文切換又包括用戶態空間切換和內核態的切換。具體的解釋可以參照英文源碼注釋以及中文對各個步驟的注釋。
其中核心函數是獲取下一個任務的pick_next_task()以及上下文切換的context_switch(),下面詳細展開剖析。首先看看pick_next_task(),該函數會根據調度策略分類,調用該類對應的調度函數選擇下一個任務實體。根據前文分析我們知道,最終是在不同的紅黑樹上選擇最左節點作為下一個任務實體並返回。
下面來看看上下文切換。上下文切換主要干兩件事情,一是切換任務空間,也即虛擬內存;二是切換寄存器和 CPU 上下文。關於任務空間的切換放在內存部分的文章中詳細介紹,這里先按下不表,通過任務空間切換實際完成了用戶態的上下文切換工作。下面我們重點看一下內核態切換,即寄存器和CPU上下文的切換。
switch_to()就是寄存器和棧的切換,它調用到了 __switch_to_asm。這是一段匯編代碼,主要用於棧的切換, 其中32位使用esp作為棧頂指針,64位使用rsp,其他部分代碼一致。通過該段匯編代碼我們完成了棧頂指針的切換,並調用__switch_to完成最終TSS的切換。注意switch_to中其實是有三個變數,分別是prev, next, last,而實際在使用時,我們會對last也賦值為prev。這里的設計意圖需要結合一個例子來說明。假設有ABC三個任務,從A調度到B,B到C,最後C回到A,我們假設僅保存prev和next,則流程如下
最終調用__switch_to()函數。該函數中涉及到一個結構體TSS(Task State Segment),該結構體存放了所有的寄存器。另外還有一個特殊的寄存器TR(Task Register)會指向TSS,我們通過更改TR的值,會觸發硬體保存CPU所有寄存器在當前TSS,並從新的TSS讀取寄存器的值載入入CPU,從而完成一次硬中斷帶來的上下文切換工作。系統初始化的時候,會調用 cpu_init()給每一個 CPU 關聯一個 TSS,然後將 TR 指向這個 TSS,然後在操作系統的運行過程中,TR 就不切換了,永遠指向這個 TSS。當修改TR的值得時候,則為任務調度。
更多Linux內核視頻教程文本資料免費領取後台私信【 內核大禮包 】自行獲取。
在完成了switch_to()的內核態切換後,還有一個重要的函數finish_task_switch()負責善後清理工作。在前面介紹switch_to三個參數的時候我們已經說明了使用last的重要性。而這里為何讓prev和last均賦值為prev,是因為prev在後面沒有需要用到,所以節省了一個指針空間來存儲last。
至此,我們完成了內核態的切換工作,也完成了整個主動調度的過程。
搶占式調度通常發生在兩種情況下。一種是某任務執行時間過長,另一種是當某任務被喚醒的時候。首先看看任務執行時間過長的情況。
該情況需要衡量一個任務的執行時間長短,執行時間過長則發起搶占。在計算機裡面有一個時鍾,會過一段時間觸發一次時鍾中斷,通知操作系統時間又過去一個時鍾周期,通過這種方式可以查看是否是需要搶占的時間點。
時鍾中斷處理函數會調用scheler_tick()。該函數首先取出當前CPU,並由此獲取對應的運行隊列rq和當前任務curr。接著調用該任務的調度類sched_class對應的task_tick()函數進行時間事件處理。
以普通任務隊列為例,對應的調度類為fair_sched_class,對應的時鍾處理函數為task_tick_fair(),該函數會獲取當前的調度實體和運行隊列,並調用entity_tick()函數更新時間。
在entity_tick()中,首先會調用update_curr()更新當前任務的vruntime,然後調用check_preempt_tick()檢測現在是否可以發起搶占。
check_preempt_tick() 先是調用 sched_slice() 函數計算出一個調度周期中該任務運行的實際時間 ideal_runtime。sum_exec_runtime 指任務總共執行的實際時間,prev_sum_exec_runtime 指上次該進程被調度時已經佔用的實際時間,所以 sum_exec_runtime - prev_sum_exec_runtime 就是這次調度佔用實際時間。如果這個時間大於 ideal_runtime,則應該被搶佔了。除了這個條件之外,還會通過 __pick_first_entity 取出紅黑樹中最小的進程。如果當前進程的 vruntime 大於紅黑樹中最小的進程的 vruntime,且差值大於 ideal_runtime,也應該被搶佔了。
如果確認需要被搶占,則會調用resched_curr()函數,該函數會調用set_tsk_need_resched()標記該任務為_TIF_NEED_RESCHED,即該任務應該被搶占。
某些任務會因為中斷而喚醒,如當 I/O 到來的時候,I/O進程往往會被喚醒。在這種時候,如果被喚醒的任務優先順序高於 CPU 上的當前任務,就會觸發搶占。try_to_wake_up() 調用 ttwu_queue() 將這個喚醒的任務添加到隊列當中。ttwu_queue() 再調用 ttwu_do_activate() 激活這個任務。ttwu_do_activate() 調用 ttwu_do_wakeup()。這裡面調用了 check_preempt_curr() 檢查是否應該發生搶占。如果應該發生搶占,也不是直接踢走當前進程,而是將當前進程標記為應該被搶占。
由前面的分析,我們知道了不論是是當前任務執行時間過長還是新任務喚醒,我們均會對現在的任務標記位_TIF_NEED_RESCUED,下面分析實際搶占的發生。真正的搶占還需要一個特定的時機讓正在運行中的進程有機會調用一下 __schele()函數,發起真正的調度。
實際上會調用__schele()函數共有以下幾個時機
從系統調用返回用戶態:以64位為例,系統調用的鏈路為do_syscall_64->syscall_return_slowpath->prepare_exit_to_usermode->exit_to_usermode_loop。在exit_to_usermode_loop中,會檢測是否為_TIF_NEED_RESCHED,如果是則調用__schele()
內核態啟動:內核態的執行中,被搶占的時機一般發生在 preempt_enable() 中。在內核態的執行中,有的操作是不能被中斷的,所以在進行這些操作之前,總是先調用 preempt_disable() 關閉搶占,當再次打開的時候,就是一次內核態代碼被搶占的機會。preempt_enable() 會調用 preempt_count_dec_and_test(),判斷 preempt_count 和 TIF_NEED_RESCHED 是否可以被搶占。如果可以,就調用 preempt_schele->preempt_schele_common->__schele 進行調度。
本文分析了任務調度的策略、結構體以及整個調度流程,其中關於內存上下文切換的部分尚未詳細敘述,留待內存部分展開剖析。
1、調度相關結構體及函數實現
2、schele核心函數
④ Linux系統進程調度
主要參考 :Linux manual page - sched
自從linux內核2.6.23以來,默認的進高嘩扮程調度器就被設置為完全公平調度器(CFS,complete fair scheler),取代了之前的O(1)調度器。
每個線程都有一個靜態調度優先順序,即 sched_priority 欄位。
一個線程的調度策略決定了線程會被插入到同級靜態優先順序的線程隊列的位置,以及它在隊列中會怎樣移動。
所有的調度都是可插入的,如果一個更高靜態優先順序的線程准備好了,現在運行中的線程就會被插入。而調度策略則僅僅影響了同樣靜態優先順序的線程。
進程(線程)可以通過系蘆橋統調用設置自身或者其他進程(線程)的調度策略。
其中 pid 為0時,設置自身的調度策略和參數。結構體 sched_attr 包含以下戚灶欄位: size 、 sched_policy (即調度策略,具體會在下一節介紹)、 sched_flags 、 sched_nice 、 sched_runtime 、 sched_deadline 、 sched_period (最後三個為 SCHED_DEADLINE 相關的參數)。當設置成功,系統調用返回0;否則返回-1,並會設置 errno 。
普通進程: SCHED_OTHER / SCHED_BATCH / SCHED_IDLE
實時進程: SCHED_FIFO / SCHED_RR
特殊實時進程: SCHED_DEADLINE
靜態優先順序:Static_priority:對於普通進程,靜態優先順序為0;對於實時進程,靜態優先順序為1-99,99為最高優先順序。
動態優先順序:Dynamic_priority:僅對普通進程有用,取決於nice和一個動態調整的量(比如進程ready卻沒被調度,則增加)。