第4章程序排程(六)

2021-08-21 14:48:38 字數 2991 閱讀 7635

4.7 實時排程策略

linux提供兩種實時排程策略:sched_fifo和sched_rr。普通的、非實時的排程策略是sched_normal。借助排程類的框架,這些實時策略被乙個特殊的實時排程器管理。具體實現定義在kernel/sched_rt.c中。

sched_fifo是一種簡單的、先入先出的排程演算法:不使用時間片。處於可執行狀態的sched_fifo級的程序比任何sched_normal級的程序先得到排程。一旦乙個sched_fifo級程序處於可執行狀態,會一直執行,直到自己受阻或顯示地釋放處理器為止,它不基於時間片,可以一直執行下去。只有更高優先順序的sched_fifo或者sched_rr任務才能搶占sched_fifo任務。如果有兩個或者更多的同優先順序的sched_fifo級程序,它們會輪流執行,但是依然只有在它們願意讓出處理器時才會退出。只要有sched_fifo級程序在執行,其它級別較低的程序就只能等待它變為不可執行態後才有機會執行。

sched_rr與sched_fifo大體相同,只是sched_rr級的程序在耗盡事先分配給它的時間後就不能再繼續執行了。sched_rr是帶有時間片的sched_fifo——是一種實時輪流排程演算法。當sched_rr任務耗盡它的時間片時,在同一優先順序的其他實時程序被輪流排程。時間片只用來重新排程同一優先順序的程序。對於sched_fifo程序,高優先順序總是立即搶占低優先順序,但低優先順序程序不能搶占sched_rr任務,即使它的時間片耗盡。

這兩種實時演算法實現的都是靜態優先順序。核心不為實時程序計算動態優先順序。這能保證給定優先順序別的實時程序總能搶占優先順序比它低的程序。

linux的實時排程演算法提供一種軟實時工作方式。軟實時含義是,核心排程程序,盡力使程序在它的限定時間到來前執行,但核心不保證總能滿足這些程序的要求。硬實時系統保證在一定條件下,可滿足任何排程的要求。linux對於實時任務的排程不做任何保證。

實時優先順序範圍從0到max_rt_prio減1。預設情況下,max_rt_prio為100——預設的實時優先順序範圍是從0到99。sched_normal(普通的、非實時程序)級程序的nice值共享了這個取值空間;它的取值範圍從max_rt_prio到(max_rt_prio+40)。在預設情況下,nice值從-20到+19直接對應的是從100到140的實時優先順序範圍。

4.8 與排程相關的系統呼叫

linux提供乙個系統呼叫族,用於管理與排程程式相關的引數。這些系統呼叫可以用來操作和處理程序優先順序、排程策略及處理器繫結,還提供了顯式地將處理器交給其他程序的機制。

1、與排程策略和優先順序相關的系統呼叫

sched_setscheduler()和sched_getscheduler()分別用於設定和獲取程序的排程策略。其實現是由許多引數檢查、初始化和清理構成的。其實最重要的工作在於讀取和設定程序task_struct的policy。

sched_setparam()和sched_getparam()分別用於設定和獲取程序的實時優先順序。這兩個系統呼叫獲取封裝在sched_param特殊結構體的sched_priority中。

sched_get_priority_max()和sched_get_priority_min()分別用於返回給定排程策略的最大和最小優先順序。實時排程策略的最大優先順序是max_user_rt_prio減1,最小優先順序等於1。

對於乙個普通的程序,nice()函式可以將給定程序的靜態優先順序增加乙個給定的量。只有超級使用者才能在呼叫它時使用負值,從而提高程序的優先順序。nice()會呼叫核心的set_user_nice(),這個函式會設定程序的task_struct的prio, static_prio值。

void set_user_nice(struct task_struct *p, long nice)

on_rq = p->se.on_rq;

if (on_rq)

dequeue_task(rq, p, 0);

p->static_prio = nice_to_prio(nice);

set_load_weight(p);

old_prio = p->prio;

p->prio = effective_prio(p);

delta = p->prio - old_prio;

if (on_rq)

out_unlock:

task_rq_unlock(rq, &flags);

}2、與處理器繫結有關的系統呼叫

linux排程程式提供強制的處理器繫結機制。雖然它盡力通過一種軟的親和性檢視使程序盡量在同乙個處理器上執行,但它也允許使用者強制指定這個程序都必須在這些處理器上執行。這種強制的親和性儲存在程序描述符task_struct的cpus_allowed這個位掩碼標誌中。該掩碼標誌的每一位對應乙個系統可用的處理器。預設,所有的位都被設定,程序可以在系統中所有可用的處理器上執行。可通過sched_setaffinity()設定不同的乙個或幾個位組合的位掩碼,而呼叫sched_getaffinity()則返回當前的cpus_allowed位掩碼。

核心提供的強制處理器繫結的方法很簡單。首先,當處理進行第一次建立時,它繼承了其父程序的相關掩碼。由於父程序執行在指定處理器上,子程序也執行在相應處理器上。其次,當處理器繫結關係改變時,核心會採用移植執行緒把任務推到合法的處理器上。最後,載入平衡器只把任務拉到允許的處理器上,因此,程序只執行在指定處理器上,對處理器的指定是由該程序描述符的cpus_allowed域設定的。

3、放棄處理器時間

linux通過sched_yield()系統呼叫,提供了一種讓程序顯式地將處理器時間讓給其他等待執行程序的機制。這是通過將程序從活動佇列中移到過期佇列中實現的。由此產生的效果不僅搶占了該程序並將其放入優先順序佇列的最後面,還將其放入過期佇列中——這樣能確保在一段時間內它都不會再被執行了。由於實時程序不會過期,所以屬於例外。現在,應用程式甚至核心**呼叫sched_yield()之前,應該仔細考慮是否真的希望放棄處理器時間。

核心**為了方便,可以直接呼叫yield(),先要確定給定程序確實處於可執行狀態,然後再呼叫sched_yield()。使用者空間的應用程式直接使用sched_yield()系統呼叫就可以了。

第4章 程序 I

4.1.1 程序例項控制代碼 載入到程序位址空間的每乙個可執行檔案或者dll檔案都被賦予了乙個獨一無二的例項控制代碼。可執行檔案的例項被昂做 w winmain函式的第乙個引數hinstanceexe傳入。在需要載入資源的函式呼叫中,一般都要提供此控制代碼的值。例如,為了從可執行檔案的映像中能夠載入...

第4章 程序管理

第四章 程序管理 入門學習 什麼是程序?程序的生命週期?程序的狀態?程序 乙個程式執行起來就是程式 生命週期 這個程式從啟動到結束的時間 程序的狀態 程序狀態有,正在執行,暫停執行,殭屍 卡機了 這個圖大家都很熟悉吧 沒錯就是我們電腦上的 任務管理器 可以在這裡面 看到我們所開啟的程式 和系統程式 ...

第4章 程序和程式

程序是由正文段 text 資料段 data segment 和系統段 system segment 共同組成的乙個執行環境。程式是乙個儲存在硬碟上的普通檔案,裡面包含 指令和資料的集合,這寫 指令和資料儲存在磁碟上的乙個可執行映像 executale image 中。linux中每個程序都是由乙個t...