進程會一直執行直到本身主動中止運行(這一步驟稱爲讓步)linux
Linux/Unix使用的是搶佔式的方式;強制的掛起進程的動做就叫作搶佔。進程在被搶佔以前可以運行的時間是預先設置好的(也就是進程的時間片)算法
(1)進程分爲I/O消耗型和處理器消耗型函數
I/O消耗型:進程的大部分時間用來提交I/O請求或是等待I/O請求。這樣的進程常常處於可運行狀態,但一般是短短一下子。由於它在等待更多的I/O請求時最後總會阻塞。ui
處理器消耗型:把時間大多用在執行代碼上。除非被搶佔,不然一直不停地運行。對於這類,調度策略儘可能下降他們的調度頻率,而延長其運行時間。spa
(2)調度策略一般在兩個矛盾的目標中間尋找平衡:進程響應迅速(響應時間短)和最大系統利用率(高吞吐量)。unix
(3)Unix系統更傾向於I/O消耗型程序,以提供更好的程序響應速度。隊列
在某些系統中,優先級高的進程使用的時間片也比較長。調度程序老是選擇時間片未用盡並且優先級最高的進程運行。用戶和系統均可以經過設置進程的優先級來影響系統的調度。進程
Linux採用了兩種不一樣的優先級範圍——nice值和實時優先級值。事件
(1) nice值,範圍是-20到19,數值越大優先級越低,默認值爲0。Linux中,nice值則表明時間片的比例。能夠經過ps-el命令查看系統中的進程列表,結果中標記NI的一列就是進程對應的nice值。內存
(2) 實時優先級值,默認0到99,數值越大優先級越高。任何實時進程的優先級都高於普通的進程。
查看進程列表以及對應的實時優先級:ps-eo state,uid,pid,ppid,rtprio,time,comm.
代表進程被搶佔前所能持續運行的時間。長時間片致使系統交互表現欠佳。
(1)Linux的CFS調度器:沒有直接分配時間片到進程,而是將處理器的使用比劃分給進程。其搶佔時機取決於新的可運行程序消耗了多少處理器使用比。若是消耗的使用比比當前進程小,馬上投入運行,搶佔當前進程;不然推遲運行。
(1)Linux調度器是以模塊方式提供的(也就是調度器類),目的是容許不一樣類型的進程能夠有針對性地選擇調度算法
(2)調度器類容許多種不一樣的可動態添加的調度算法並存,調度屬於本身範疇的進程;
(3)調度器代碼會按照優先級順序遍歷調度類,擁有一個可執行進程的最高優先級的調度器類勝出,去選擇下面要執行的那一個程序;
(1)將nice值映射到時間片的話,就必須將nice值對應處處理器的絕對時間;這樣會致使進程切換沒法最優進行;
(2)若是使用相對nice值,所帶來的效果將會極大取決於其nice的初始值;
(3)若是執行nice值到時間片的映射,時間片極大受制於定時器。
目標延遲:CFS爲完美多任務中的無限小調度週期的近似值設立的一個目標。越小的調度週期將帶來越好的交互性,同時也更接近完美的多任務。但必須承受更高的切換代價和更差的系統總吞吐能力。
最小粒度:CFS引人每一個進程得到的時間片底線,這個底線稱爲最小粒度。
CFS中,任何進程所得到的處理器時間是由它本身和其餘全部可運行進程nice值的相對差值決定。任何nice值對應的絕對時間是處理器的使用比。
(1)CFS算法核心:選擇具備最小vrntime的任務
(2)具體作法:利用紅黑樹rbtree(以節點形式存儲數據的二叉樹)
(1)進程調度的主要入口點是函數schedule(),定義在kernel/sched.c中;這正是內和其餘部分用於調度進程調度器的入口
(2)這一函數最重要的工做就是調用pick_next_state(),依次檢查每個調度類,並從最高優先級的調度類中,選擇最高優先級進程
(1)進程休眠必定是爲了等待一些事件
(2)喚醒操做由函數wake_up()進行
上下文切換由定義在kernel/sched.c中的context_switch()函數負責,每當一個新的進程被選出來準備運行的時候,schedule()就會調用該函數:
發生時機:
從中斷處理程序返回用戶空間時。
(1)只要沒有鎖,內核就能夠進程搶佔;
(2)爲了支持搶佔,每一個進程的thread_info都加入了preempt_count計數器(初值爲0,每當使用鎖的時候就加1,釋放鎖的時候數值減1),當數值爲0時,內核就能夠搶佔
(3)內核搶佔發生在:
linux 提供兩種實時調度策略SCHED_FIFO和SCHED_RR。