A. linux內核設計與實現 進程調度1: 基本概念
進程大致可分為I/O密集型和 CPU密集型。
調度依據 動態優先順序 ,所謂動態優先順序就是初始化時給出一個基礎優先順序,隨後優先順序可被調度程序動態的增減。高優先順序進程也獲得較長的時間片。I/O密集型通常被提升優先順序,而CPU密集型則被降低。
Linux系統有兩種獨立的優先順序范圍。第一種是 Nice 值,返回是[-20, 19],默認值為0。數值越高優先順序越低。Nice值影響了時間片的分配。如果進程擁有-20的Nice值,那麼該進程將被分配理論最長的時間片。Nice值是所有Unix系統的標准優先順序。
Linux的第二種優先順序范圍是 實時優先順序 。這個優先順序的值是可配置的。通常來說范圍在[0,99]。 所有實時進程的優先順序都高於普通進程 。(實時進程是什麼?)
時間片是一個數值,決定了進程被搶占前可運行的時間。必須為進程分配合適長度的時間片。時間片太長會影響系統的交互性,時間片太短則會導致系統花費大量的時間用於進程的切換。同時還要兼顧I/O密集型和 CPU密集型進程的矛盾。因為I/O密集型無需長時間片,卻渴望經常運行。而Linux卻提供了相對較長的默認時間片——100毫秒。
注意到,進程不必在每次被調度運行後就花光自己所有的時間片。舉例來說,如果一個進程擁有長達100毫秒的時間片,那麼它可以在五個不同時段運行,每次花費20毫秒的時間片。這么做的好處是,一個擁有長時間片的進程(盡管它本身不需要如此長的時間片),可以盡可能長時間的保持運行狀態。而不會過早地被丟入等待調度的隊列中(稍後說到)。這就好比鍵盤驅動進程的實現方法。
當某進程的狀態變為TASK_RUNNING的時候,內核會檢查它的優先順序是否高於當前正在執行的任務。如果是,調度進程就會使該進程搶佔CPU。另外,如果一個進程的時間片變成0(意味著用盡了所有時間片,只能等待所有進程時間片為0才會重新分配),調度進程會被再次調用,選擇一個新的進程運行。
個人猜測 :這里拿文字軟體和音樂播放軟體來舉例。CPU在每條指令執行結束後檢查中斷引腳。如果檢測到鍵盤的活動,就會引發中斷而將鍵盤輸入程序的狀態設置為TASK_RUNNING,然後執行上述的檢查程序。因為文字軟體的優先順序高於音樂播放軟體,所以文字軟體將立即得到執行,將鍵入字元輸入在屏幕中。完成這一工作後,文字軟體將設置自身狀態或是其他方法,使得音樂播放軟體可以搶佔CPU?
B. linux內核怎麼調度系統
1.調度器的概述
多任務操作系統分為非搶占式多任務和搶占式多任務。與大多數現代操作系統一樣,Linux採用的是搶占式多任務模式。這表示對CPU的佔用時間由操作系統決定的,具體為操作系統中的調度器。調度器決定了什麼時候停止一個進程以便讓其他進程有機會運行,同時挑選出一個其他的進程開始運行。
2.調度策略
在Linux上調度策略決定了調度器是如何選擇一個新進程的時間。調度策略與進程的類型有關,內核現有的調度策略如下:
#define SCHED_NORMAL 0#define SCHED_FIFO 1#define SCHED_RR 2#define SCHED_BATCH 3/* SCHED_ISO: reserved but not implemented yet */#define SCHED_IDLE 5
0: 默認的調度策略,針對的是普通進程。
1:針對實時進程的先進先出調度。適合對時間性要求比較高但每次運行時間比較短的進程。
2:針對的是實時進程的時間片輪轉調度。適合每次運行時間比較長得進程。
3:針對批處理進程的調度,適合那些非交互性且對cpu使用密集的進程。
SCHED_ISO:是內核的一個預留欄位,目前還沒有使用
5:適用於優先順序較低的後台進程。
註:每個進程的調度策略保存在進程描述符task_struct中的policy欄位
3.調度器中的機制
內核引入調度類(struct sched_class)說明了調度器應該具有哪些功能。內核中每種調度策略都有該調度類的一個實例。(比如:基於公平調度類為:fair_sched_class,基於實時進程的調度類實例為:rt_sched_class),該實例也是針對每種調度策略的具體實現。調度類封裝了不同調度策略的具體實現,屏蔽了各種調度策略的細節實現。
調度器核心函數schele()只需要調用調度類中的介面,完成進程的調度,完全不需要考慮調度策略的具體實現。調度類連接了調度函數和具體的調度策略。
武特師兄關於sche_class和sche_entity的解釋,一語中的。
調度類就是代表的各種調度策略,調度實體就是調度單位,這個實體通常是一個進程,但是自從引入了cgroup後,這個調度實體可能就不是一個進程了,而是一個組
4.schele()函數
linux 支持兩種類型的進程調度,實時進程和普通進程。實時進程採用SCHED_FIFO 和SCHED_RR調度策略,普通進程採用SCHED_NORMAL策略。
preempt_disable():禁止內核搶占
cpu_rq():獲取當前cpu對應的就緒隊列。
prev = rq->curr;獲取當前進程的描述符prev
switch_count = &prev->nivcsw;獲取當前進程的切換次數。
update_rq_clock() :更新就緒隊列上的時鍾
clear_tsk_need_resched()清楚當前進程prev的重新調度標志。
deactive_task():將當前進程從就緒隊列中刪除。
put_prev_task() :將當前進程重新放入就緒隊列
pick_next_task():在就緒隊列中挑選下一個將被執行的進程。
context_switch():進行prev和next兩個進程的切換。具體的切換代碼與體系架構有關,在switch_to()中通過一段匯編代碼實現。
post_schele():進行進程切換後的後期處理工作。
5.pick_next_task函數
選擇下一個將要被執行的進程無疑是一個很重要的過程,我們來看一下內核中代碼的實現
對以下這段代碼說明:
1.當rq中的運行隊列的個數(nr_running)和cfs中的nr_runing相等的時候,表示現在所有的都是普通進程,這時候就會調用cfs演算法中的pick_next_task(其實是pick_next_task_fair函數),當不相等的時候,則調用sched_class_highest(這是一個宏,指向的是實時進程),這下面的這個for(;;)循環中,首先是會在實時進程中選取要調度的程序(p = class->pick_next_task(rq);)。如果沒有選取到,會執行class=class->next;在class這個鏈表中有三種類型(fair,idle,rt).也就是說會調用到下一個調度類。
在這段代碼中體現了Linux所支持的兩種類型的進程,實時進程和普通進程。回顧下:實時進程可以採用SCHED_FIFO 和SCHED_RR調度策略,普通進程採用SCHED_NORMAL調度策略。
在這里首先說明一個結構體struct rq,這個結構體是調度器管理可運行狀態進程的最主要的數據結構。每個cpu上都有一個可運行的就緒隊列。剛才在pick_next_task函數中看到了在選擇下一個將要被執行的進程時實際上用的是struct rq上的普通進程的調度或者實時進程的調度,那麼具體是如何調度的呢?在實時調度中,為了實現O(1)的調度演算法,內核為每個優先順序維護一個運行隊列和一個DECLARE_BITMAP,內核根據DECLARE_BITMAP的bit數值找出非空的最高級優先隊列的編號,從而可以從非空的最高級優先隊列中取出進程進行運行。
我們來看下內核的實現
數組queue[i]裡面存放的是優先順序為i的進程隊列的鏈表頭。在結構體rt_prio_array 中有一個重要的數據構DECLARE_BITMAP,它在內核中的第一如下:
5.1對於實時進程的O(1)演算法
這個數據是用來作為進程隊列queue[MAX_PRIO]的索引點陣圖。bitmap中的每一位與queue[i]對應,當queue[i]的進程隊列不為空時,Bitmap的相應位就為1,否則為0,這樣就只需要通過匯編指令從進程優先順序由高到低的方向找到第一個為1的位置,則這個位置就是就緒隊列中最高的優先順序(函數sched_find_first_bit()就是用來實現該目的的)。那麼queue[index]->next就是要找的候選進程。
如果還是不懂,那就來看兩個圖
由結果可以看出當nice的值越小的時候,其睡眠時間越短,則表示其優先順序升高了。
7.關於獲取和設置優先順序的系統調用:sched_getscheler()和sched_setscheler
輸出結果:
可以看出進程的優先順序已經被改變。
C. 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卻沒被調度,則增加)。
D. Linux中如何啟動進程進程調度命令有哪些
Linux技術的發展引起了很多企業和個人的關注。市場對Linux運維的需求逐漸增加,學習Linux技術的人越來越多。在Linux運維中,進程是必須學習掌握的技能。那麼Linux中如何啟動進程?常用的進程調度命令有哪些? 執行中的程序稱作進程。當程序的可執行文件存儲在存儲器中並運行時,每個進程將被動態分配系統資源、內存、安全屬性和相關狀態。多個進程可以與同一個程序相關聯,並在同一時間執行,而不會相互干擾。操作系統將有效地管理和跟蹤所有正在運行的進程。 Linux中如何啟動進程?啟動進程的方法是什麼? 手工啟動。用戶在輸入端發出命令,直接啟動進程。分為前台啟動和後台啟動。前台啟動:直接在SHELL中輸入命令進行啟動。後台啟動:啟動一個目前並不緊急的進程。 調度啟動。系統管理員根據系統資源和進程佔用資源的情況,事先進行調度安排,指定任務運行的時間和場合,到時候系統會自動完成該任務。 常用的進程調度命令有哪些? 常用的進程調度命令有:at、batch、crontab。 以上便是關於「如何啟動或終止進程?常用的進程調度命令有哪些?」的相關介紹。想要成為一名優秀的Linux運維工程師,需要掌握更多的Linux知識。E. linux kernel功能有哪些
1、系統調用介面
提供系統的API函數,供用戶使用,例如操作文件的函數、操作進程和線程的函數、操作內存的函數、操作硬體(如串口、磁碟)的函數、操作網路的函數等等。
2、實現進程管理功能
能夠同時(看上去)執行多個進程(任務),比如可以同時運行文件下載、看電影、掛游戲,那麼進程管理的內部實現就是進程的調度,也就是實現調度CPU的使用時間提供給不同的用戶任務(進程)使用。
3、實現虛擬文件系統
所謂虛擬文件系統,即是相對於實際文件系統的系統,其實是針對實際文件系統再次的實現和介面的抽象,意思是規定了最終提供給用戶使用的文件系統的介面。
以及實現實際文件系統調用硬體層的介面,那麼實際文件系統就是位於虛擬文件系統和硬體抽象介面中間,就像是夾心餅干中間的奶油一樣,可以更換各種顏色的奶油,但是吃起來都是奶油的味道,可便於系統的更新和前後的兼容性、擴展性。
(5)linux進程管理和調度擴展閱讀:
技術特性
1、搶占式調度系統
Linux內核提供在特定條件下的搶先式調度。直到內核版本2.4,只有用戶進程是搶先式的,就是說除了時間片用盡,在用戶模式下執行的當前進程,如果有更高態優先順序的進程進入TASK_RUNNING狀態,它就會被中斷。
自從2.6系列Linux內核,增加了中斷執行內核代碼的任務的能力,但不是對於內核代碼的所有段落。
2、可移植性
從行動電話到超級電腦,甚至於有人成功的將Linux內核在索尼出品的游戲機PS2及PS3和微軟出品的游戲機Xbox上使用。Linux也是IBM超級計算機BlueGene的操作系統。
一些為手機開發的操作系統,使用Linux內核的修改後的版本,其中包括谷歌Android、FirefoxOS、HPWebOS和諾基亞Maemo。
F. Linux進程調度的概述
在Linux中,進程的運行時間不可能超過分配給他們的時間片,他們採用的是搶占式多任務處理,所回以進程之間的掛起和繼答續運行無需彼此之間的協作。
在一個如linux這樣的多任務系統中,多個程序可能會競爭使用同一個資源,在這種情況下,我們認為,執行短期的突發性工作並暫停運行以等待輸入的程序,要比持續佔用處理器以進行計算或不斷輪詢系統以查看是否有輸入到達的程序要更好。我們稱表現好的程序為nice程序,而且在某種意義上,這個nice 是可以被計算出來的。操作系統根據進程的nice值來決定它的優先順序,一個進程的nice值默認為0並將根據這個程序的表現不斷變化。長期不間斷運行的程序的優先順序一般會比較低。