為什麼會發生排程?
因為cpu是有限的,而作業系統上的程序很多,所以作業系統需要平衡各個程序的執行時間
比如說有的程序執行時間已經很長了,已經占用了cpu很長時間了,這個時候作業系統要公平
就會換下乙個需要執行的程序。
舉個例子
公司只有乙個飲水機用來接水,有很多人排隊,某個人接完了一杯水,又接下一杯水,一連線了好多杯水,這個時候公司的人事就要過來把這個人趕走
換下乙個人接水,然而這個時候老闆過來接水了,這個時候下乙個人就是老闆來接水,而不是後面排隊的人,因為什麼呢?因為他是老闆,就這麼強悍
這裡面的飲水機就是cpu
人事就是作業系統
等接水的乙個個員工就是程序
老闆就對應作業系統裡的實時程序
普通員工就對應作業系統的普通程序
在作業系統裡面實時程序的優先順序比普通程序的優先順序要高,
所以作業系統在選擇下個程序的時候會優先選擇實時程序佇列裡面的程序
除非實時程序裡面的程序沒有了,這個時候才輪到普通程序
作業系統就像人事一樣,需要公平的排程和分配資源,當然公司裡面有很多老闆啊,總經理啊,領導啊
這些人擁有特權,所有分配資源的時候要優先考慮這些老闆領導們,這也很正常,誰讓人家是老闆呢
下面來說說搶占式排程
什麼情況下會發生搶占式排程呢?
最常見的現象是你這個程序執行時間太長了,是時候切換到另乙個程序了
然而作業系統怎麼去統計執行時間呢?
計算機有個時鐘的概念,每過一段時間,計算機會通知作業系統,告訴作業系統,又過去了一段時間,你去看看,當前執行的程序執行時間是不是過長了,這個時候作業系統就會去搞這個程序了。
在作業系統中對於每個程序有乙個理想執行時間的變數,然後對應還有乙個虛擬執行時間和實際執行時間和權重(優先順序)。
這三者有什麼關係呢?
虛擬執行時間 vruntime += 實際執行時間 delta_exec * nice_0_load/ 權重(優先順序)
通過這個公式可以看出來,給高優先順序的程序的虛擬執行時間算少了,給低優先順序的程序的虛擬執行時間算多了,但是當作業系統選擇下乙個程序的時候還是選擇虛擬執行時間最少的程序,所以說優先順序在這裡面就體現出來了。
當某個程序在執行的時候,這個程序的虛擬執行時間會增加,當程序不執行的時候,虛擬時間不增加
其實這裡又會涉及到排程器的概念。
這裡我們就只說針對普通程序的絕對公平排程策略
這種策略在選取下個程序的時候,是怎麼選取的呢?
他是選取當前所有普通程序中執行時間最少的程序,這個應該很好理解吧,因為你在cpu上占用的時間最少,所以為了公平,就要選取你這個程序在cpu上執行。
在作業系統中維護了乙個紅黑樹,紅黑樹就是一顆平衡二叉樹,也就是說紅黑樹上面掛了好多程序,最左邊的程序就是執行時間最少的程序,所有作業系統在,選取下乙個程序就會選取這個紅黑樹上最左側的程序。
static void
check_preempt_tick(struct cfs_rq *cfs_rq, struct sched_entity *curr)
unsigned long ideal_runtime, delta_exec;
struct sched_entity *se;
s64 delta;
ideal_runtime = sched_slice(cfs_rq, curr);
delta_exec = curr->sum_exec_runtime - curr->prev_sum_exec_runtime;
if (delta_exec > ideal_runtime) {
resched_curr(rq_of(cfs_rq));
return;
se = __pick_first_entity(cfs_rq);
delta = curr->vruntime - se->vruntime;
if (delta < 0)
return;
if (delta > ideal_runtime)
resched_curr(rq_of(cfs_rq));
上面**是linux原始碼
在作業系統中還有個時間的概念,就是在乙個排程週期中,這個程序應該執行的實際時間(ideal_runtime)
sum_exec_runtime指程序總共執行的實際時間, prev_sum_exec_runtime指上次該程序被排程時已經占用的實際時間。
每次在排程乙個新的程序時都會把它的se->prev_sum_exec_runtime=se->sum_exec_runtime,所以sum_exec_runtime-prev_sum_exec_runtime
就是這次排程占用實際時間。如果這個時間大於ideal_runtime,則應該被搶占了。
除了這個條件外,還會通過_pick_first_entity取出紅黑樹中最小的程序。如果當前程序的vruntime(虛擬執行時間)大於紅黑樹中最小的程序的vruntime,且差值大於ideal_time,也應該
被搶占了
當發現這個程序應該被搶占了,不能直接把他踢下去,而是在這個程序上打乙個標籤tif_need_resched,標示這個程序可以被搶占了
還有乙個可能發生搶占的場景,就是當乙個休眠的程序被喚醒的時候
這個時候如果這個被喚醒的程序比當前執行的程序的優先順序高,則也應該被搶占了,也是在當前執行的程序上打乙個標籤tif_need_resched
搶占的時機
1.使用者態的搶占時機
當該程序進行系統呼叫從核心態返回到使用者態的時候,判斷如果該程序有tif_need_resched標籤,則進行搶占。
2.核心態的搶占時機
對核心態的執行中,被搶占的時機一般發生在preempt_enable()中。
preempt_disable()關閉搶占
在核心態的執行中,有的操作是不能被中斷的,所有在進行這些操作之前,總是先呼叫preempt_disable()關閉搶占,當再次開啟的時候,也就是呼叫preempt_enable()的時候
就是一次核心態**被搶占的機會。
在核心態也會遇到中斷的情況,當中斷返回的時候,返回的仍然是核心態度。這個時候也是乙個執行搶占的時機。
大家可以看看這張圖理解
作業系統課程實驗報告(四)
程序執行軌跡的跟蹤和統計 還是 那門課的實驗,把它從實驗樓搬過來了。這個實驗的目的 需要在 linux 0.11 中建立乙個 log檔案用來收集 linux 0.11 執行中所有程序建立 切換以及退出的狀態。為此,我們需要在系統初始化的時候建立乙個 log檔案,用來記錄 需要乙個 fprintk 函...
作業系統實驗報告三 16281028
系統呼叫的進一步理解。程序上下文切換。同步與通訊方法。通過fork的方式,產生4個程序p1,p2,p3,p4,每個程序列印輸出自己的名字,例如p1輸出 i am the process p1 要求p1最先執行,p2 p3互斥執行,p4最後執行。通過多次測試驗證實現是否正確。實驗結果 在p2和p3之間...
作業系統第2次實驗報告 建立程序
列印1所建立的程序樹結構,給出帶有自己名字的截圖。uid 使用者id號 pid process id 程序 id號 ppid parent process id 父程序 id號 c 占用cpu的量,圖中為0 stime 建立該程序的時間 tty 登入者的終端機位置 time 使用掉的cpu時間 cm...