edf調度演算法
Ⅰ PD稱為什麼控制演算法
PD稱為基於優先順序的調度演算法(Priority-driven scheling-PD),基於優先順序的調度演算法給每個進程分配一個優先順序,在每次進程調度時,調度器總是調度那個具有最高優先順序的任務來執行。根據不同的優先順序分配方法,基於優先順序的調度演算法可以分為如下兩種類型[Krishna01][Wang99]:1、靜態優先順序調度演算法:這種調度演算法給那些系統中得到運行的所有進程都靜態地分配一個優先順序。靜態優先順序的分配可以根據應用的屬性來進行,比如任務的周期,用戶優先順序,或者其它的預先確定的策略卜搭碧。RM(Rate-Monotonic)調度演算法是一種典型的靜態優先順序調度演算法,它根據任務的執行周期的長短來決定調度優先順序,那些具有小的執行周期的任務具有較高的優先順序。2、動態優先順序調枝困度演算法:這種調度演算法根據任務的資源需求來動態地分配任務的優先順序,其目的就是在資源分配和調度時有更大的靈活性。非實時系統中就有很多這種調度演算法,比如短作業優先的調度演算法。在實時調度演算法中, EDF演算法是使用最多的一種動態優先順序調度演算法,該演算法給就緒隊列中的各型舉個任務根據它們的截止期限(Deadline)來分配優先順序,具有最近的截止期限的任務具有最高的優先順序。
Ⅱ 股票中的edf是什麼意思
EDF全稱Earliest Deadline First。最早截止時間優先演算法(EDF)也稱為截止時間驅動調度演算法(DDS),是一種動態調度演算法。EDF在調度時,任務的優先順序根據任務的截止時間動態分配。截止時間越短,優先順序越高。如果一個任務集負載U<=1,則是可調度的。EDF 調度演算法已被證明是動態最優調度, 而且是充要條件。處理機利用率最大可達100% 。但瞬時過載時, 系統行為不可預測, 可能發生多米諾骨牌現象, 一個任務丟失時會引起一連串的任務接連丟失。
拓展資料
股票中的標的是什麼意思:標的證券是投資者融入資大乎旅金可買入的證券和證券公司可對投資者融出的證券。證券交易所按照從嚴到寬、從少到多、逐步擴大的原則,根據融資融券業務試點的進展情況,在滿足證券交易所規定的證券范圍內審核、選取試點初期標的證券的名單,並向市場公布。證券公司在上述范圍內確定並公布該公司允許的標的證券。證券交易所規定融資買入標的證券和融券賣出標的證券限於其認可的上市股頃頌票、證券投資基金、及其他證券。
作為標的證券的股票應當符合的條件
1、在證券交易所上市交易滿3個月;
2、融資買入標的股票的流通股本不少於1億股或流通市值不低於5億元,融券賣出標的股票的流通股本不少於2億股或流通市值不低於8億元;
3、股票發行公司的股東人數不少於4000人;
4、近3個月內日均換手率不低於基準指數日均換手率的20%,日均漲跌幅的平均值與基準指數漲跌幅的平均值的偏離值不超過4個百分點滾凳;且波動幅度不超過基準指數波動幅度的500%以上; 日均換手率是指過去3個月內標的證券或基準指數每日換手率的平均值。
日均漲跌幅是指過去3個月內標的證券或基準指數每日漲跌幅絕對值的平均值。 波動幅度是指過去3個月內標的證券或基準指數最高價與最低價之差對最高價和最低價的平均值之比。 對於基準指數,在上海交易所是指上證綜合指數,在深圳交易所是指深證綜合指數和中小板指數。
5、股票發行公司已完成股權分置改革;
6、股票交易未被證券交易所實行特別處理;
7、證券交易所規定的其他條件。
Ⅲ 實時調度的單處理器實時調度
問題描述:假設一任務集S={t1,t2,t3,...,tn},周期分別是T1,T2,...,Tn,執行時間為c1,c2,...,cn,deadline為D1,D2,...,Dn,Di=Ti。任務ti可以被搶占。
CPU利用率用U=sum(ci/Ti)來表示。對於單處理器,U<=1是S可調度的前提條件,否則S不可調度。 任務按單調速率優先順序分配(RMPA)的調度演算法,稱為單調速率調度(RMS)。RMPA是指任務的優先順序按任務周期T來分配。它根據任務的執行周期的長短來決定調度優先順序,那些具有小的執行周期的任務具有較高的優先順序,周期長的任務優先順序低。
不考慮n=1的情況。RMS是單處理器下的最優靜態調度演算法。1973年Liu和Layland發表的這篇文章的前半部分首次提出了RM調度演算法在靜態調度中的最優性. 它的一個特點是可通過對系統資源利用率的計算來進行任務可調度性分析, 演算法簡單、有效, 便於實現。不僅如此, 他們還把系統的利用系數(utilization factor)和系統可調度性聯系起來, 推導出用RM調度所能達到的最小系統利用率公式. 同時, 這篇論文中透露出來的證明思想和方法也被人們所效仿. 下面就讓我們來看看這篇文章中關於RM調度演算法的重要結論。
任何一個結論都有一個模型假設, 讓我們先列出這里的假設:
(A1) 所有的任務請求都是周期性的,必須在限定的時限內完成;
(A2) 任務的作業必須在該任務的下一個作業發生之前完成, 這樣避免了考慮隊列問題; 在這里, 我們對任務和作業不作特別的區分, 因為一個任務請求就是一個作業。
(A3) 任務之間都是獨立的,每個任務的請求不依賴於其他任務請求的開始或完成;
(A4) 每個任務的運行時間是不變的,這里任務的運行時間是指處理器在無中斷情況下用於處理該任務的時間;
(A5) 所有的非周期性任務都在特殊的情況下運行,比如系統初始化或系統非正常緊急處理程序。
(A6) 其它一些假設, 比如, 單處理器, 可搶占調度, 任務切換的時間忽略不計等等。 (1) 任務T i (P i, Ci, D i) 模型: 周期為P i,計算時間為Ci, 時限D i 為周期終點。任務在周期起點釋放, 高優先順序任務可搶占低優先順序任務的執行。
(2) 優先順序分配方法: 靜態固定分配。優先順序與周期成反比, 周期越短優先順序越高。
(3) 可調度性分析: 如果任務集滿足下式, 則該任務集可調度。
定理1:n個獨立的周期任務可以被RMPA調度,如果U<=n(2^(1/n)-1)。
一個任務的響應時間(response time)是指一個任務請求到這個任務實際完成的時間跨度. 在靜態調度中, 任務的臨界時刻(critical instant)這個概念被首先提出來. 它被定義為一個特定的時刻, 如果在這個時刻任務請求到來, 那麼會導致這個任務的響應時間最大(A critical instant of a task is the time atwhich the release of a task will proce the largestresponse time). 由此得出
定理1: 一個任務的臨界時刻就是比這個任務優先順序高的所有任務同時發出請求的時刻.
(Lemma: For any task, the critical instant occurs if thattask is simultaneously released with all higher prioritytasks .)
證明: 由於一個任務的響應時間是它自己的負載時間加上被其它優先順序高的任務所打斷的時間. 由於自己的負載時間是固定的, 我們考慮在什麼時候任一高優先順序的任務會有最長的打斷時間. 顯然, 只有當這一高優先順序的任務與該任務同時請求處理時, 才能可能產生最大的打斷時間.
如果有任務1和任務2,且任務1的優先順序比任務2高,那麼任務2的響應時間會被任務1延遲。
當任務1的請求到來的更早,那麼任務2的響應時間就更長了。
定理1的價值在於它找到了一個用於證明一個調度演算法能否調度任一任務集的充分必要條件。那就是所有任務同時請求執行的情況下,每個任務仍能滿足各自的期限, 那麼這個任務集就可以被這個調度演算法調度.
有了這個推論, 我們就可以證明RM調度的最優性了.
定理2: 如果一個任務集能夠被靜態調度, 那麼RMS演算法就能夠調度這個任務集. 從這個意義上說, RMS是最優的靜態調度演算法.
這個定理的證明方法就是有名的交換法. 證明思路如下:
假設一個任務集S採用其他靜態優先順序演算法可以調度,那麼總有這樣兩個優先順序相鄰的任務i和j, 有Ti>Tj,而Pi≤Pj.把Ti和Tj的優先順序Pi和Pj互換,明顯可以看出這時S仍然可以調度, 因為在所有任務同時請求的情況下, 交換這兩個任務不會影響其它任務的完成時間, 同時這兩個任務都可以在各自期限內完成. 按照這樣的方法,其他任何靜態優先順序調度最終都可以轉換成RM調度.
RMS已被證明是靜態最優調度演算法, 開銷小, 靈活性好, 是實時調度的基礎性理論。即使系統瞬時過載, 也完全可預測哪些任務丟失時限。缺點是處理機利用率較低, 最壞的情況下,當n→∞時, 不超過ln2 (≈ 70%)。另外, RMS是充分但非必要條件。而在一般情況下,對於隨機的任務集大約只有88%. 70%或者88%的處理器利用率對於許多實時應用來說是一個嚴重的限制,動態調度演算法如最早截止期最先(earliest deadline first,EDF)或者最少空閑時間最先(least laxity first,LLF)已經被證明是最優的,並且能夠實現100% 的處理器利用率. 最早截止時間優先演算法(EDF)也稱為截止時間驅動調度演算法(DDS),是一種動態調度演算法。EDF指在調度時,任務的優先順序根據任務的截止時間動態分配。截止時間越短,優先順序越高。EDF有如下定理:
定理2:如果一個任務集按EDF演算法調度,當且僅當U<=1。
EDF的特點
(1) 任務模型: 與RMS 調度相同。
(2) 優先順序分配方法: 動態分配, 距要求時限所剩時間越短優先順序越高。
(3) 可調度性分析: 如果任務集滿足下式, 則該任務集可調度。
EDF 調度演算法已被證明是動態最優調度, 而且是充要條件。處理機利用率最大可達100% 。但瞬時過載時, 系統行為不可預測, 可能發生多米諾骨牌現象, 一個任務丟失時會引起一連串的任務接連丟失。另外, 它的在線調度開銷比RMS大。 最短空閑時間優先演算法(LLF)也是一種動態調度演算法。LLF指在調度時刻,任務的優先順序根據任務的空閑時間動態分配。空閑時間越短,優先順序越高。空閑時間=deadline-任務剩餘執行時間。LLF可調度條件和EDF相同。
理論上,EDF和LLF演算法都是單處理器下的最優調度演算法。但是由於EDF和LLF在每個調度時刻都要計算任務的deadline或者空閑時間,並根據計算結果改變任務優先順序,因此開銷大、不易實現,其應用受到一定限制。
Ⅳ 如何用C語言實現EDF,LSF調度演算法
#include<stdio.h>voidmain()指磨旁{char*a[3][3]={{"sssd","sda","scsdf"唯橡},{"ere","edf","vadfd"},{"sah","hyt","tye"}};inti,j;游辯for(i=0;i<3;i++)for(j=0;j<3;j++)printf("%s",a[i][j]);}
Ⅳ 電梯調度演算法...
不管你是在北上廣還是在港澳台,甚至三四線城市,凡是有規模的地區,高樓比比皆是。不管是寫字樓,還是大型商城,讓你最頭痛的就是乘電梯,尤其是在趕時間的時候。
每天早上,那些差5分鍾就遲到的程序員,在等電梯時,一般會做兩件事:
前者可能是寫字樓里上班族慣有的精神類疾病,但後者肯定是程序員的職業病。本文對「罵電梯」不給予任何指導性建議。
但說起電梯調度演算法,我覺得還是可以給大家科普一下,好為大家在等電梯之餘,打發時間而做出一點貢獻。
(電梯調度演算法可以參考各種硬碟換道演算法,下面內容整理自網路)
先來先服務(FCFS-First Come First Serve)演算法,是一種隨即服務演算法,它不僅僅沒有對尋找樓層進行優化,也沒有實時性的特徵,它是一種最簡單的電梯調度演算法。
它根據乘客請求乘坐電梯的先後次序進行調度。此演算法的 優點是公平、簡單,且每個乘客的請求都能依次地得到處理,不會出現某一乘客的請求長期得不到滿足的情況 。
這種方法在載荷較輕松的環境下,性能尚可接受,但是在載荷較大的情況下,這種演算法的性能就會嚴重下降,甚至惡化。
人們之所以研究這種在載荷較大的情況下幾乎不可用的演算法,有兩個原因:
最短尋找樓層時間優先(SSTF-Shortest Seek Time First)演算法,它注重電梯尋找樓層的優化。最短尋找樓層時間優先演算法選擇下一個服務對象的原則是 最短尋找樓層的時間。
這樣請求隊列中距當前能夠最先到達的樓層的請求信號就是下一個服務對象。
在重載荷的情況下,最短尋找樓層時間優先演算法的平均響應時間較短,但響應時間的方差較大 ,原因是隊列中的某些請求可能長時間得不到響應,出現所謂的「 餓死」現象 。
掃描演算法(SCAN) 是一種按照樓層順序依次服務請求,它讓電梯在最底層和最頂層之間連續往返運行,在運行過程中響應處在於電梯運行方向相同的各樓層上的請求。
它進行尋找樓層的優化,效率比較高,但它是一個 非實時演算法 。掃描演算法較好地解決了電梯移動的問題,在這個演算法中,每個電梯響應乘客請求使乘客獲得服務的次序是由其發出請求的乘客的位置與當前電梯位置之間的距離來決定的。
所有的與電梯運行方向相同的乘客的請求在一次電向上運行或向下運行的過程中完成, 免去了電梯頻繁的來回移動 。
掃描演算法的平均響應時間比最短尋找樓層時間優先演算法長,但是響應時間方差比最短尋找樓層時間優先演算法小, 從統計學角度來講,掃描演算法要比最短尋找樓層時間優先演算法穩定 。
LOOK 演算法是掃描演算法(SCAN)的一種改進。對LOOK演算法而言,電梯同樣在最底層和最頂層之間運行。
但 當 LOOK 演算法發現電梯所移動的方向上不再有請求時立即改變運行方向 ,而掃描演算法則需要移動到最底層或者最頂層時才改變運行方向。
SATF(Shortest Access Time First)演算法與 SSTF 演算法的思想類似,唯一的區別就是 SATF 演算法將 SSTF 演算法中的尋找樓層時間改成了訪問時間。
這是因為電梯技術發展到今天,尋找樓層的時間已經有了很大地改進, 但是電梯的運行當中等待乘客上梯時間卻不是人為可以控制 。
SATF 演算法考慮到了電梯運行過程中乘客上梯時間的影響 。
最早截止期優先(EDF-Earliest Deadline First)調度演算法是最簡單的實時電梯調度演算法,它的 缺點就是造成電梯任意地尋找樓層,導致極低的電梯吞吐率。
它與 FCFS 調度演算法類似,EDF 演算法是電梯實時調度演算法中最簡單的調度演算法。 它響應請求隊列中時限最早的請求,是其它實時電梯調度演算法性能衡量的基準和特例。
SCAN-EDF 演算法是 SCAN 演算法和 EDF 演算法相結合的產物。SCAN-EDF 演算法先按照 EDF 演算法選擇請求列隊中哪一個是下一個服務對象,而對於具有相同時限的請求,則按照 SCAN 演算法服務每一個請求。它的效率取決於有相同 deadline 的數目,因而效率是有限的。
PI(Priority Inversion)演算法將請求隊列中的請求分成兩個優先順序,它首先保證高優先順序隊列中的請求得到及時響應,再搞優先順序隊列為空的情況下在相應地優先順序隊列中的請求。
FD-SCAN(Feasible Deadline SCAN)演算法首先從請求隊列中找出時限最早、從當前位置開始移動又可以買足其時限要求的請求,作為下一次 SCAN 的方向。
並在電梯所在樓層向該請求信號運行的過程中響應處在與電梯運行方向相同且電梯可以經過的請求信號。
這種演算法忽略了用 SCAN 演算法相應其它請求的開銷,因此並不能確保服務對象時限最終得到滿足。
以上兩結介紹了幾種簡單的電梯調度演算法。
但是並不是說目前電梯調度只發展到這個層次。目前電梯的控制技術已經進入了電梯群控的時代。
隨著微機在電梯系統中的應用和人工智慧技術的發展,智能群控技術得以迅速發展起來。
由此,電梯的群控方面陸續發展出了一批新方法,包括:基於專家系統的電梯群控方法、基於模糊邏輯的電梯群控方法、基於遺產演算法的電梯群控方法、基於勝景網路的電梯群控方法和基於模糊神經網路的電梯群控方法。
本人設置的電梯的初始狀態,是對住宅樓的電梯的設置。
(1)建築共有21層,其中含有地下一層(地下一層為停車場)。
(2)建築內部設有兩部電梯,編號分別為A梯、B梯。
(3)電梯內部有23個按鈕,其中包括開門按鈕、關門按鈕和樓層按鈕,編號為-1,1,2,3,4……20。
(4)電梯外部含有兩個按鈕,即向上運行按鈕和向下運行按鈕。建築頂層與地下一層例外,建築頂層只設置有向下運行按鈕,地下一層只設置有向上運行按鈕。
(5)電梯開關門完成時間設定為1秒。電梯到達每層後上下人的時間設定為8秒。電梯從靜止開始運行到下一層的時間設置為2秒,而運行中通過一層的時間為1秒。
(6)在凌晨2:00——4:30之間,如若沒有請求信號,A梯自動停在14層,B梯自動停在6層。
(7)當電梯下到-1層後,如果沒有請求信號,電梯自動回到1層。
每一架電梯都有一個編號,以方便監控與維修。每一架電梯都有一實時監控器,負責監控電梯上下,向電梯升降盒發送啟動、制動、加速、減速、開關電梯門的信號。若電梯發生故障,還應向相應的電梯負責人發送求救信號。
電梯內部的樓層按鈕:
這樣就表示乘客將要去往此層,電梯將開往相應層。當電梯到達該層後,按鈕恢復可以使用狀態。
電梯內部開門按鈕:
如若電梯到了乘客曾經按下的樓層,但是無乘客按開門按鈕,電梯將自動在停穩後1秒後自動開門。
電梯內部關門按鈕:
電梯外部向上按鈕:
電梯外部向下按鈕:
你肯能意識到 哪個演算法都不是一個最佳方案,只是它確實解決了一定情況的問題 。但是對一個優秀的程序員而言,研究各種演算法是無比快樂的。也許你下一次面試,就有關於調度演算法的問題。
Ⅵ 設有周期性實時任務集如下表所示,用 edf 演算法和 rms 算 法是否可以調度
分布式實時謹喚皮調度演算法可以分為兩類:
1)以RMS為基礎的廣義RMS調度
2)以風車調度Sr為基礎的DSr調度 定義:設?X={Xi}是一個分布式的任務集合,1≤i≤n,分布式系統中有祥差m個節點,對於Xi∈X,Xi={Ti1,?Ti2,…,?Tim},Tij是Xi在Nj節點上的任務,Xi有距離約束ci。鏈慎對於Tij?有執行時間eij。
定義lk=ck/2「lg(ck/cl), Bik=lk·2lg(ci/lk)」。
ΦNj(lk)=∑eij/Bik,(i=1..n)為調度任務集在節點Nj上的密度。
選擇一個使∑ΦNj(lk),j=1..m)最小值的lk作為系統的劃分基r*。?
演算法前提: 所有的任務有相同的執行節點,每個任務在網路節點上有同樣的距離約束。
Ⅶ 什麼是最早截止時間優先調度演算法
最早截如伏止時間優先(Earliest Dealine First, EDF)是實時系統中常用的一種調度演算法,系統中有多個任務時,由調度演算法扒者決定哪個任務當前佔用處理器,那麼EDF演算法就是按照任務的截止時間(deadline)來確定任務的執行順序,最早截止的任務先執春橡薯行。
Ⅷ linux環境下的進程調度演算法有哪些
第一部分: 實時調度演算法介紹
對於什麼是實時系統,POSIX 1003.b作了這樣的定義:指系統能夠在限定的響應時間內提供所需水平的服務。而一個由Donald Gillies提出的更加為大家接受的定義是:一個實時系統是指計算的正確性不僅取決於程序的邏輯正確性,也取決於結果產生的時間,如果系統的時間約束條件得不到滿足,將會發生系統出錯。
實時系統根據其對於實時性要求的不同,可以分為軟實時和硬實時兩種類型。硬實時系統指系統要有確保的最壞情況下的服務時間,即對於事件的響應時間的截止期限是無論如何都必須得到滿足。比如航天中的宇宙飛船的控制等就是現實中這樣的系統。其他的所有有實時特性的系統都可以稱之為軟實時系統。如果明確地來說,軟實時系統就是那些從統計的角度來說,一個任務(在下面的論述中,我們將對任務和進程不作區分)能夠得到有確保的處理時間,到達系統的事件也能夠在截止期限到來之前得到處理,但違反截止期限並不會帶來致命的錯誤,像實時多媒體系統就是一種軟實時系統。
一個計算機系統為了提供對於實時性的支持,它的操作系統必須對於CPU和其他資源進行有效的調度和管理。在多任務實時系統中,資源的調度和管理更加復雜。本文下面將先從分類的角度對各種實時任務調度演算法進行討論,然後研究普通的 Linux操作系統的進程調度以及各種實時Linux系統為了支持實時特性對普通Linux系統所做的改進。最後分析了將Linux操作系統應用於實時領域中時所出現的一些問題,並總結了各種實時Linux是如何解決這些問題的。
1. 實時CPU調度演算法分類
各種實時操作系統的實時調度演算法可以分為如下三種類別[Wang99][Gopalan01]:基於優先順序的調度演算法(Priority-driven scheling-PD)、基於CPU使用比例的共享式的調度演算法(Share-driven scheling-SD)、以及基於時間的進程調度演算法(Time-driven scheling-TD),下面對這三種調度演算法逐一進行介紹。
1.1. 基於優先順序的調度演算法
基於優先順序的調度演算法給每個進程分配一個優先順序,在每次進程調度時,調度器總是調度那個具有最高優先順序的任務來執行。根據不同的優先順序分配方法,基於優先順序的調度演算法可以分為如下兩種類型[Krishna01][Wang99]:
靜態優先順序調度演算法:
這種調度演算法給那些系統中得到運行的所有進程都靜態地分配一個優先順序。靜態優先順序的分配可以根據應用的屬性來進行,比如任務的周期,用戶優先順序,或者其它的預先確定的策略。RM(Rate-Monotonic)調度演算法是一種典型的靜態優先順序調度演算法,它根據任務的執行周期的長短來決定調度優先順序,那些具有小的執行周期的任務具有較高的優先順序。
動態優先順序調度演算法:
這種調度演算法根據任務的資源需求來動態地分配任務的優先順序,其目的就是在資源分配和調度時有更大的靈活性。非實時系統中就有很多這種調度演算法,比如短作業優先的調度演算法。在實時調度演算法中, EDF演算法是使用最多的一種動態優先順序調度演算法,該演算法給就緒隊列中的各個任務根據它們的截止期限(Deadline)來分配優先順序,具有最近的截止期限的任務具有最高的優先順序。
1.2. 基於比例共享調度演算法
雖然基於優先順序的調度演算法簡單而有效,但這種調度演算法提供的是一種硬實時的調度,在很多情況下並不適合使用這種調度演算法:比如象實時多媒體會議系統這樣的軟實時應用。對於這種軟實時應用,使用一種比例共享式的資源調度演算法(SD演算法)更為適合。
比例共享調度演算法指基於CPU使用比例的共享式的調度演算法,其基本思想就是按照一定的權重(比例)對一組需要調度的任務進行調度,讓它們的執行時間與它們的權重完全成正比。
我們可以通過兩種方法來實現比例共享調度演算法[Nieh01]:第一種方法是調節各個就緒進程出現在調度隊列隊首的頻率,並調度隊首的進程執行;第二種做法就是逐次調度就緒隊列中的各個進程投入運行,但根據分配的權重調節分配個每個進程的運行時間片。
比例共享調度演算法可以分為以下幾個類別:輪轉法、公平共享、公平隊列、彩票調度法(Lottery)等。
比例共享調度演算法的一個問題就是它沒有定義任何優先順序的概念;所有的任務都根據它們申請的比例共享CPU資源,當系統處於過載狀態時,所有的任務的執行都會按比例地變慢。所以為了保證系統中實時進程能夠獲得一定的CPU處理時間,一般採用一種動態調節進程權重的方法。
1.3. 基於時間的進程調度演算法
對於那些具有穩定、已知輸入的簡單系統,可以使用時間驅動(Time-driven:TD)的調度演算法,它能夠為數據處理提供很好的預測性。這種調度演算法本質上是一種設計時就確定下來的離線的靜態調度方法。在系統的設計階段,在明確系統中所有的處理情況下,對於各個任務的開始、切換、以及結束時間等就事先做出明確的安排和設計。這種調度演算法適合於那些很小的嵌入式系統、自控系統、感測器等應用環境。
這種調度演算法的優點是任務的執行有很好的可預測性,但最大的缺點是缺乏靈活性,並且會出現有任務需要被執行而CPU卻保持空閑的情況。
2. 通用Linux系統中的CPU調度
通用Linux系統支持實時和非實時兩種進程,實時進程相對於普通進程具有絕對的優先順序。對應地,實時進程採用SCHED_FIFO或者SCHED_RR調度策略,普通的進程採用SCHED_OTHER調度策略。
在調度演算法的實現上,Linux中的每個任務有四個與調度相關的參數,它們是rt_priority、policy、priority(nice)、counter。調度程序根據這四個參數進行進程調度。
在SCHED_OTHER 調度策略中,調度器總是選擇那個priority+counter值最大的進程來調度執行。從邏輯上分析,SCHED_OTHER調度策略存在著調度周期(epoch),在每一個調度周期中,一個進程的priority和counter值的大小影響了當前時刻應該調度哪一個進程來執行,其中 priority是一個固定不變的值,在進程創建時就已經確定,它代表了該進程的優先順序,也代表這該進程在每一個調度周期中能夠得到的時間片的多少; counter是一個動態變化的值,它反映了一個進程在當前的調度周期中還剩下的時間片。在每一個調度周期的開始,priority的值被賦給 counter,然後每次該進程被調度執行時,counter值都減少。當counter值為零時,該進程用完自己在本調度周期中的時間片,不再參與本調度周期的進程調度。當所有進程的時間片都用完時,一個調度周期結束,然後周而復始。另外可以看出Linux系統中的調度周期不是靜態的,它是一個動態變化的量,比如處於可運行狀態的進程的多少和它們priority值都可以影響一個epoch的長短。值得注意的一點是,在2.4以上的內核中, priority被nice所取代,但二者作用類似。
可見SCHED_OTHER調度策略本質上是一種比例共享的調度策略,它的這種設計方法能夠保證進程調度時的公平性--一個低優先順序的進程在每一個epoch中也會得到自己應得的那些CPU執行時間,另外它也提供了不同進程的優先順序區分,具有高priority值的進程能夠獲得更多的執行時間。
對於實時進程來說,它們使用的是基於實時優先順序rt_priority的優先順序調度策略,但根據不同的調度策略,同一實時優先順序的進程之間的調度方法有所不同:
SCHED_FIFO:不同的進程根據靜態優先順序進行排隊,然後在同一優先順序的隊列中,誰先准備好運行就先調度誰,並且正在運行的進程不會被終止直到以下情況發生:1.被有更高優先順序的進程所強佔CPU;2.自己因為資源請求而阻塞;3.自己主動放棄CPU(調用sched_yield);
SCHED_RR:這種調度策略跟上面的SCHED_FIFO一模一樣,除了它給每個進程分配一個時間片,時間片到了正在執行的進程就放棄執行;時間片的長度可以通過sched_rr_get_interval調用得到;
由於Linux系統本身是一個面向桌面的系統,所以將它應用於實時應用中時存在如下的一些問題:
Linux系統中的調度單位為10ms,所以它不能夠提供精確的定時;
當一個進程調用系統調用進入內核態運行時,它是不可被搶占的;
Linux內核實現中使用了大量的封中斷操作會造成中斷的丟失;
由於使用虛擬內存技術,當發生頁出錯時,需要從硬碟中讀取交換數據,但硬碟讀寫由於存儲位置的隨機性會導致隨機的讀寫時間,這在某些情況下會影響一些實時任務的截止期限;
雖然Linux進程調度也支持實時優先順序,但缺乏有效的實時任務的調度機制和調度演算法;它的網路子系統的協議處理和其它設備的中斷處理都沒有與它對應的進程的調度關聯起來,並且它們自身也沒有明確的調度機制;
3. 各種實時Linux系統
3.1. RT-Linux和RTAI
RT -Linux是新墨西哥科技大學(New Mexico Institute of Technology)的研究成果[RTLinuxWeb][Barabanov97]。它的基本思想是,為了在Linux系統中提供對於硬實時的支持,它實現了一個微內核的小的實時操作系統(我們也稱之為RT-Linux的實時子系統),而將普通Linux系統作為一個該操作系統中的一個低優先順序的任務來運行。另外普通Linux系統中的任務可以通過FIFO和實時任務進行通信。RT-Linux的框架如圖 1所示:
圖 1 RT-Linux結構
RT -Linux的關鍵技術是通過軟體來模擬硬體的中斷控制器。當Linux系統要封鎖CPU的中斷時時,RT-Linux中的實時子系統會截取到這個請求,把它記錄下來,而實際上並不真正封鎖硬體中斷,這樣就避免了由於封中斷所造成的系統在一段時間沒有響應的情況,從而提高了實時性。當有硬體中斷到來時, RT-Linux截取該中斷,並判斷是否有實時子系統中的中斷常式來處理還是傳遞給普通的Linux內核進行處理。另外,普通Linux系統中的最小定時精度由系統中的實時時鍾的頻率決定,一般Linux系統將該時鍾設置為每秒來100個時鍾中斷,所以Linux系統中一般的定時精度為 10ms,即時鍾周期是10ms,而RT-Linux通過將系統的實時時鍾設置為單次觸發狀態,可以提供十幾個微秒級的調度粒度。
RT-Linux實時子系統中的任務調度可以採用RM、EDF等優先順序驅動的演算法,也可以採用其他調度演算法。
RT -Linux對於那些在重負荷下工作的專有系統來說,確實是一個不錯的選擇,但他僅僅提供了對於CPU資源的調度;並且實時系統和普通Linux系統關系不是十分密切,這樣的話,開發人員不能充分利用Linux系統中已經實現的功能,如協議棧等。所以RT-Linux適合與工業控制等實時任務功能簡單,並且有硬實時要求的環境中,但如果要應用與多媒體處理中還需要做大量的工作。
義大利的RTAI( Real-Time Application Interface )源於RT-Linux,它在設計思想上和RT-Linux完全相同。它當初設計目的是為了解決RT-Linux難於在不同Linux版本之間難於移植的問題,為此,RTAI在 Linux 上定義了一個實時硬體抽象層,實時任務通過這個抽象層提供的介面和Linux系統進行交互,這樣在給Linux內核中增加實時支持時可以盡可能少地修改 Linux的內核源代碼。
3.2. Kurt-Linux
Kurt -Linux由Kansas大學開發,它可以提供微秒級的實時精度[KurtWeb] [Srinivasan]。不同於RT-Linux單獨實現一個實時內核的做法,Kurt -Linux是在通用Linux系統的基礎上實現的,它也是第一個可以使用普通Linux系統調用的基於Linux的實時系統。
Kurt-Linux將系統分為三種狀態:正常態、實時態和混合態,在正常態時它採用普通的Linux的調度策略,在實時態只運行實時任務,在混合態實時和非實時任務都可以執行;實時態可以用於對於實時性要求比較嚴格的情況。
為了提高Linux系統的實時特性,必須提高系統所支持的時鍾精度。但如果僅僅簡單地提高時鍾頻率,會引起調度負載的增加,從而嚴重降低系統的性能。為了解決這個矛盾, Kurt-Linux採用UTIME所使用的提高Linux系統中的時鍾精度的方法[UTIMEWeb]:它將時鍾晶元設置為單次觸發狀態(One shot mode),即每次給時鍾晶元設置一個超時時間,然後到該超時事件發生時在時鍾中斷處理程序中再次根據需要給時鍾晶元設置一個超時時間。它的基本思想是一個精確的定時意味著我們需要時鍾中斷在我們需要的一個比較精確的時間發生,但並非一定需要系統時鍾頻率達到此精度。它利用CPU的時鍾計數器TSC (Time Stamp Counter)來提供精度可達CPU主頻的時間精度。
對於實時任務的調度,Kurt-Linux採用基於時間(TD)的靜態的實時CPU調度演算法。實時任務在設計階段就需要明確地說明它們實時事件要發生的時間。這種調度演算法對於那些循環執行的任務能夠取得較好的調度效果。
Kurt -Linux相對於RT-Linux的一個優點就是可以使用Linux系統自身的系統調用,它本來被設計用於提供對硬實時的支持,但由於它在實現上只是簡單的將Linux調度器用一個簡單的時間驅動的調度器所取代,所以它的實時進程的調度很容易受到其它非實時任務的影響,從而在有的情況下會發生實時任務的截止期限不能滿足的情況,所以也被稱作嚴格實時系統(Firm Real-time)。目前基於Kurt-Linux的應用有:ARTS(ATM Reference Traffic System)、多媒體播放軟體等。另外Kurt-Linux所採用的這種方法需要頻繁地對時鍾晶元進行編程設置。
3.3. RED-Linux
RED -Linux是加州大學Irvine分校開發的實時Linux系統[REDWeb][ Wang99],它將對實時調度的支持和Linux很好地實現在同一個操作系統內核中。它同時支持三種類型的調度演算法,即:Time-Driven、 Priority-Dirven、Share-Driven。
為了提高系統的調度粒度,RED-Linux從RT-Linux那兒借鑒了軟體模擬中斷管理器的機制,並且提高了時鍾中斷頻率。當有硬體中斷到來時,RED-Linux的中斷模擬程序僅僅是簡單地將到來的中斷放到一個隊列中進行排隊,並不執行真正的中斷處理程序。
另外為了解決Linux進程在內核態不能被搶占的問題, RED-Linux在Linux內核的很多函數中插入了搶占點原語,使得進程在內核態時,也可以在一定程度上被搶占。通過這種方法提高了內核的實時特性。
RED-Linux的設計目標就是提供一個可以支持各種調度演算法的通用的調度框架,該系統給每個任務增加了如下幾項屬性,並將它們作為進程調度的依據:
Priority:作業的優先順序;
Start-Time:作業的開始時間;
Finish-Time:作業的結束時間;
Budget:作業在運行期間所要使用的資源的多少;
通過調整這些屬性的取值及調度程序按照什麼樣的優先順序來使用這些屬性值,幾乎可以實現所有的調度演算法。這樣的話,可以將三種不同的調度演算法無縫、統一地結合到了一起。
Ⅸ 時間片輪轉調度演算法的演算法
多級反饋隊列調度演算法
(1) 設置多個就緒隊列,並為各個隊列賦予不同的優先順序. 第一個隊列的優先順序最高,第二個隊列次之,其餘各隊列的優先權逐個降低.
該演算法賦予各個隊列中進程執行時間片的大小也各不相同:
在優先權愈高的隊列中,為每個進程所規定的執行時間片就愈小.
例如:第二個隊列的時間片要比第一個隊列的時間片長一倍,……,第i+1個隊列的時間片要比第i個隊列的時間片長一倍.
(2) 當一個新進程進入內存後,首先將它放入第一隊列的末尾,按FCFS原則排隊等待調度.當輪到該進程執行時,如它能在該時間片內完成,便可准備撤離系統;如果它在一個時間片結束時尚未完成,調度程序便將該進程轉入第二隊列的末尾,再同樣地按FCFS原則等待調度執行;如果它在第二隊列中運行一個時間片後仍未完成,再依次將它放入第三隊列,……,如此下去,當一個長作業(進程)從第一隊列依次降到第n隊列後,在第n隊列中便採取按時間片輪轉的方式運行.
(3) 僅當第一隊列空閑時,調度程序才調度第二隊列中的進程運行; 僅當第1~(i-1) 隊列均空時,才會調度第i隊列中的進程運行.如果處理機正在第i隊列中為某進程服務時,又有新進程進入優先權較高的隊列(第1~(i-1)中的任何一個隊列),則此時新進程將搶占正在運行進程的處理機,即由調度程序把正在運行的進程放回到第i隊列的末尾,把處理機分配給新到的高優先權進程.?
性能
(1)終端型作業用戶
(2) 短批處理作業用戶
(3) 長批處理作業用戶
滿足了多數用戶的需求 優先權調度演算法
1,優先權調度演算法的類型
非搶占式優先權演算法
在這種方式下,系統一旦把處理機分配給就緒隊列中優先權最高的進程後,該進程便一直執行下去,直至完成; 或因發生某事件使該進程放棄處理機時,系統方可再將處理機重新分配給另一優先權最高的進程.這種調度演算法主要用於批處理系統中;也可用於某些對實時性要求不嚴的實時系統中.
搶占式優先權調度演算法
系統同樣把處理機分配給優先權最高的進程,使之執行.但在其執行期間,只要又出現了另一個其優先權更高的進程,進程調度程序就立即停止當前進程(原優先權最高的進程)的執行,重新將處理機分配給新到的優先權最高的進程.
這種搶占式的優先權調度演算法,能更好地滿足緊迫作業的要求,常用於要求比較嚴格的實時系統中, 以及對性能要求較高的批處理和分時系統中.
2,優先權的類型
(1) 靜態優先權
靜態優先權是在創建進程時確定的,且在進程的整個運行期間保持不變.
一般地,優先權是利用某一范圍內的一個整數來表示的,例如,0~7或0~255中的某一整數, 又把該整數稱為優先數.只是具體用法各異:有的系統用0表示最高優先權,當數值愈大時,其優先權愈低;而有的系統恰恰相反.
確定進程優先權的依據有如下三個方面:
1.進程類型.(系統進程/用戶進程)
2.進程對資源的需求.(需求量的大小)
3.用戶要求.(用戶進程緊迫程度)
(2) 動態優先權
動態優先權是指在創建進程時所賦予的優先權,可以隨進程的推進或隨其等待時間的增加而改變的,以便獲得更好的調度性能.
例如,我們可以規定,在就緒隊列中的進程,隨其等待時間的增長,其優先權以速率a提高.若所有的進程都具有相同的優先權初值,則顯然是最先進入就緒隊列的進程,將因其動態優先權變得最高而優先獲得處理機,此即FCFS演算法.
優先權的變化規律可描述為:
由於等待時間與服務時間之和,就是系統對該作業的響應時間,故該優先權又相當於響應比RP.據此,又可表示為:
3,高響應比優先調度演算法
由上面的式子可以得到以下結論:
(1) 如果作業的等待時間相同,則要求服務的時間愈短,其優先權愈高,因而該演算法有利於短作業.
(2) 當要求服務的時間相同時,作業的優先權決定於其等待時間,等待時間愈長,其優先權愈高,因而它實現的是先來先服務.
(3) 對於長作業,作業的優先順序可以隨等待時間的增加而提高,當其等待時間足夠長時,其優先順序便可升到很高, 從而也可獲得處理機.
該演算法照顧了短作業,且不會使長作業長期得不到服務 1. 非搶占式調度演算法
為每一個被控對象建立一個實時任務並將它們排列成一輪轉隊列,調度程序每次選擇隊列中的第一個任務投入運行.該任務完成後便把它掛在輪轉隊列的隊尾等待下次調度運行.
2. 非搶占式優先調度演算法.
實時任務到達時,把他們安排在就緒隊列的對首,等待當前任務自我終止或運行完成後才能被調度執行.
3. 搶占式調度演算法
1)基於時鍾中斷的搶占式優先權調度演算法.
實時任務到達後,如果該任務的優先順序別高於當前任務的優先順序並不立即搶占當前任務的處理機,而是等到時鍾中斷到來時,調度程序才剝奪當前任務的執行,將處理機分配給新到的高優先權任務.
2)立即搶占的優先權調度演算法.
在這種調度策略中,要求操作系統具有快速響應外部時間中斷的能力.一旦出現外部中斷,只要當前任務未處於臨界區便立即剝奪當前任務的執行,把處理機分配給請求中斷的緊迫任務,實時進程調度,實時進程搶占當前。 1 實現實時調度的基本條件
1-1. 提供必要的信息-就緒時間.
1-2. 開始截止時間和完成截止時間.
1-3. 處理時間.
1-4. 資源要求.
1-5. 優先順序.
2. 系統處理能力強
在實時系統中,通常都有著多個實時任務.若處理機的處理能力不夠強,則有可能因處理機忙不過來而使某些實時任務不能得到及時處理, 從而導致發生難以預料的後果.假定系統中有m個周期性的硬實時任務,它們的處理時間可表示為Ci,周期時間表示為Pi,則在單處理機情況下,系統可調度必須滿足下面的限制條件:
當系統不可調度時解決的方法是提高系統的處理能力,其途徑有二:
其一仍是採用單處理機系統,但須增強其處理能力, 以顯著地減少對每一個任務的處理時間;
其二是採用多處理機系統.假定系統中的處理機數為N,則應將上述的限制條件改為:
3. 採用搶占式調度機制
當一個優先權更高的任務到達時,允許將當前任務暫時掛起,而令高優先權任務立即投入運行.採用這種方式去滿足那些開始截止時間即將到來的任務.?
4. 具有快速切換機制
應具有的能力:
(1) 對外部中斷的快速響應能力.為使在緊迫的外部事件請求中斷時系統能及時響應,要求系統具有快速硬體中斷機構,還應使禁止中斷的時間間隔盡量短,以免耽誤時機(其它緊迫任務).?
(2) 快速的任務分派能力.在完成任務調度後,便應進行任務切換.為了提高分派程序進行任務切換時的速度, 應使系統中的每個運行功能單位適當的小,以減少任務切換的時間開銷.實時調度實例
一, 最早截止時間優先演算法(EDF)
EDF演算法用於非搶占調度方式
優先順序:根據任務的開始截止時間來確定任務的優先順序.
二,最低鬆弛優先演算法(LLF)
例如:系統中有兩個周期性實時任務A和B,任務A要求每20ms執行一次,執行時間為10ms;任務B要求每50ms執行一次,執行時間為25ms.這樣可知A和B每次必須完成的時間和開始截止時間如圖所示
優先順序:根據任務緊急程度來確定任務優先順序
A和B任務每次必須完成的時間
A1 (10) A2 (30) A3(50) A4 (70) A5(90) A6 (110) A7(130) A8(150)
0 、10、 20、 30 、40、 50 、60、 70、 80 、90 、100 、110、 120、130、 140、 150
B1(25) B2(75) B3(125)
A和B任務每次必須開始的時間
時間(ms) A截止時間 B截止時間 調度對象
0 A1(10) B1(25) A1
10 A2(20) B1(15) B1
30 A2(0) B1(15) A2
40 A3(10) B1(5) B1
45 A3(5) B2(30) A3
55 A4(15) B2(20) B2
70 A4(0) B2(20) A4
鬆弛度
鬆弛度
( 20-10-0 ) ( 50-25-0 )
(40-10-10 ) ( 50-25-10 )
(40-10-30) (50-5-30)
(60-10-40) (50-5-40)
(60-10-45) (100-25-45)
(80-10-55) (100-25-55)
(80-10-70) (100-10-70 )
3.4.1 多處理器系統的類型
(1) 緊密耦合(Tightly Coupted)MPS.
這通常是通過高速匯流排或高速交叉開關,來實現多個處理器之間的互連的.它們共享主存儲器系統和I/O設備,並要求將主存儲器劃分為若干個能獨立訪問的存儲器模塊,以便多個處理機能同時對主存進行訪問.系統中的所有資源和進程,都由操作系統實施統一的控制和管理.
3.4 多處理機系統中的調度
從處理器之間耦合的緊密程度上劃分:
鬆散耦合(Loosely Coupled)MPS.
在鬆散耦合MPS中,通常是通過通道或通信線路,來實現多台計算機之間的互連.每台計算機都有自己的存儲器和I/O設備,並配置了OS來管理本地資源和在本地運行的進程.因此,每一台計算機都能獨立地工作, 必要時可通過通信線路與其它計算機交換信息,以及協調它們之間的工作.
根據系統中所用處理器的相同與否劃分:
(1) 對稱多處理器系統SMPS. 在系統中所包含的各處理器單元,在功能和結構上都是相同的,當前的絕大多數MPS都屬於SMP系統.例如,IBM公司的SR/6000 Model F50, 便是利用4片Power PC處理器構成的.?
(2) 非對稱多處理器系統.在系統中有多種類型的處理單元,它們的功能和結構各不相同,其中只有一個主處理器,有多個從處理器:
1. 對稱多處理器系統中的進程分配方式
在SMP系統中,所有的處理器都是相同的,因而可把所有的處理器作為一個處理器池(Processor pool),由調度程序或基於處理器的請求,將任何一個進程分配給池中的任何一個處理器去處理.在進行進程分配時,可採用以下兩種方式之一.
1) 靜態分配(Static Assigenment)方式
2) 動態分配(Dynamic Assgement)方式?
3.4.2 進程分配方式
靜態分配(Static Assigenment)方式
一個進程從開始執行直到完成,都被固定分配到一個處理器上去執行.
2) 動態分配(Dynamic Assgement)方式
系統中設置有公共的就緒隊列.分配進程時,可以將進程分配到任何一個處理器上.
動態分配方式的主要優點是消除了各處理器忙閑不均的現象
2. 非對稱MPS中的進程分配方式?
對於非對稱MPS,其OS大多採用主—從(Master-Slave)式OS,即OS的核心部分駐留在一台主機上(Master),而從機(Slave)上只是用戶程序,進程調度只由主機執行.每當從機空閑時,便向主機發送一索求進程的信號,然後,便等待主機為它分配進程.在主機中保持有一個就緒隊列,只要就緒隊列不空,主機便從其隊首摘下一進程分配給請求的從機.從機接收到分配的進程後便運行該進程,該進程結束後從機又向主機發出請求.
缺點:對主機要求高,出現故障導致整個系統癱瘓
1. 自調度(Self-Scheling)方式
1) 自調度機制?
在系統中設置有一個公共的進程或線程就緒隊列, 所有的處理器在空閑時,都可自己到該隊列中取得一進程(或線程)來運行.在自調度方式中,可採用在單處理機環境下所用的調度演算法,如先來先服務(FCFS)調度演算法,最高優先權優先(FPF)調度演算法和搶占式最高優先權優先調度演算法等.
3.4.3 進程(線程)調度方式
2) 自調度方式的優點?
1,系統中的公共就緒隊列可按照單處理機系統中所採用的各種方式加以組織;其調度演算法也可沿用單處理機系統所用的演算法,即很容易將單處理機環境下的調度機制移植到多處理機系統中
2,只要系統中有任務(公共就緒隊列不空)就不會出現處理機空閑的情況,也不會發生處理器忙閑不均的現象,因而有利於提高處理器的利用率.
3)自調度方式的缺點
3.4.4進程調度過程
1、進程名:作為進程的標識。
指針:進程按順序排成循環鏈表,用指針指出下一個進程的進程式控制制塊首地址,最後一個進程中的指針指出第一個進程的進程式控制制塊首地址。
2、要求運行時間:假設進程需要運行的單位時間數。
已運行時間:假設進程已經運行的單位時間數,初值為0。
狀態:可假設有兩種狀態,就緒狀態和結束狀態。進程的初始狀態都為就緒狀態。
3、每次運行所設計的處理器調度程序調度進程之前,為每個進程任意確定它的要求運行時間。
4、此程序是模擬處理器調度,因此,被選中的進程並不實際啟動運行,而是執行
已運行時間+1
來模擬進程的一次運行,表示進程已經運行過一個單位時間。
.5、在所設計的程序中應有顯示或列印語句,能顯示或列印每次被選中的進程名以及運行一次後進程隊列的變化。
6、為進程任意確定要求運行時間,運行所設計的處理器調度程序,顯示或列印逐次被選中進程的進程名以及進程式控制制塊的動態變化過程。
7、設有一個就緒隊列,就緒進程按優先數(優先數范圍0-100)由小到大排列(優先數越小,級別越高)。當某一進程運行完一個時間片後,其優先順序應下調(如優先數加2或3)。
8、例如一組進程如下表: 進程名 A B C D E F G H J K L M 到達時間 0 1 2 3 6 8 12 12 12 18 25 25 服務時間 6 4 10 5 1 2 5 10 4 3 15 8
Ⅹ 編寫代碼實現作業的三種調度演算法
#include<windows.h>
#include<iostream>
#include<stdio.h>
#include<string>
using namespace std;
const int maxnum=100;
int N; /*進程數*/
double start[maxnum],endtime[maxnum],arrive[maxnum],runtime[maxnum],zhou[maxnum];
double averagezhou; // 平均周轉時間
double average_zhou; //平均帶權周轉時間
char name; //進程名
double dqzhou[maxnum]; //帶權周轉時間
typedef struct node
{
char name[10]; //進程名
int round; //進程時間輪轉時間片
int cputime; //進程佔用CPU時間
int needtime; //進程到完成還要的時間
char state; //進程的狀態
struct node *next; //鏈指針
}PCB;
PCB *finish,*ready,*tail,*run; /*隊列指針*/
void firstin() /*將就緒隊列中的第一個進程投入運行*/
{
run=ready; /*就緒隊列頭指針賦值給運行頭指針*/
run->state='R'; /*進程狀態變為運行態*/
ready=ready->next; /*就緒對列頭指針後移到下一進程*/
}
void print1(PCB *q) /*進程PCB輸出*/
{
printf("進程名 已運行時間 還需要時間 時間片 狀態\n");
printf(" %-10s%-15d%-10d%-10d %-c\n",q->name,q->cputime,q->needtime,q->round,q->state);
}
void print() /*輸出函數*/
{
PCB *p;
if(run!=NULL) /*如果運行指針不空*/
print1(run); /*輸出當前正在運行的PCB*/
p=ready; /*輸出就緒隊列PCB*/
while(p!=NULL)
{
print1(p);
p=p->next;
}
p=finish; /*輸出完成隊列的PCB*/
while(p!=NULL)
{
print1(p);
p=p->next;
}
}
void insert(PCB *p2) //輪轉法插入函數
{
tail->next=p2; //將新的PCB插入在當前就緒隊列的尾
tail=p2;
p2->next=NULL;
}
void create() /*創建進程PCB*/
{
PCB *p;
int i,time;
char na[10];
ready=NULL;
finish=NULL;
run=NULL;
printf("請輸入進程名稱和所需要CPU的時間:\n");
for(i=1;i<=N;i++)
{
p=(PCB *)malloc(sizeof(PCB));
scanf("%s",na);
scanf("%d",&time);
strcpy(p->name,na);
p->cputime=0;
p->needtime=time;
if(i==1)
p->state='R';
else
p->state='W';
p->round=1; /*時間片*/
if(ready!=NULL)
insert(p);
else
{
p->next=ready;
ready=p;
tail=p;
}
}
printf("------------------------------------------------------------------\n");
print(); /*輸出進程PCB信息*/
run=ready; /*將就緒隊列的第一個進程投入運行*/
ready=ready->next;
run->state='R';
}
void RR() //時間片輪轉調度
{
while(run!=NULL)
{
run->cputime=run->cputime+1;
run->needtime=run->needtime-1;
if(run->needtime==0) /*運行完將其變為完成態,插入完成隊列*/
{
run->next=finish;
finish=run;
run->state='F';
run=NULL;
if(ready!=NULL)
firstin(); /*就緒對列不空,將第一個進程投入運行*/
}
else
if(ready!=NULL) /*如就緒隊列不空*/
{
run->state='W'; /*將進程插入到就緒隊列中等待輪轉*/
insert(run);
firstin(); /*將就緒對列的第一個進程投入運行*/
}
printf("------------------------------------------------------------------\n");
print(); /*輸出進程信息*/
}
}
void FCFS(double *arrive,double *runtime,double n) //先來先服務調度演算法
{
start[0]=arrive[0]; //開始執行時間=到達時間
endtime[0]=start[0]+runtime[0]; //完成時間=開始時間+服務時間
zhou[0]=endtime[0]-arrive[0]; //周轉時間=完成時間-到達時間
dqzhou[0]=zhou[0]/runtime[0];
for(int i=0;i<n;i++)
{
if(endtime[i-1]>arrive[i]||endtime[i-1]==arrive[i])
endtime[i]=endtime[i-1]+runtime[i];
else
endtime[i]=arrive[i]+runtime[i];
zhou[i]=endtime[i]-arrive[i];
dqzhou[i]=zhou[i]/runtime[i];
averagezhou+=zhou[i];
average_zhou+=dqzhou[i];
}
averagezhou=averagezhou/n;
average_zhou=average_zhou/n;
cout<<"完成時間為:"<<endl;
for(int j=0;j<n;j++)
cout<<endtime[j]<<" "<<endl;
cout<<"周轉時間為:"<<endl;
for(int k=0;k<n;k++)
cout<<zhou[k]<<" "<<endl;
cout<<"帶權周轉時間為:"<<endl;
for(int m=0;m<n;m++)
cout<<dqzhou[m]<<" "<<endl;
cout<<"平均周轉時間為:"<<endl;
cout<<averagezhou<<" "<<endl;
cout<<"平均帶權周轉時間為:"<<endl;
cout<<average_zhou<<" "<<endl;
}
void SJF(double *arrive,double *runtime,double n) //短作業優先調度演算法
{
int end[maxnum]; //用於標記進程是否已經執行,應經執行end[i]=1,否則為0;
for(int k=0;k<n;k++)
end[k]=0;
int temp,now=0,next=1,p=1; //now表示剛執行完的進程號,next表示下一個要執行的進程號
start[0]=arrive[0]; //開始執行時間=到達時間
endtime[0]=start[0]+runtime[0]; //完成時間=開始時間+服務時間
zhou[0]=endtime[0]-arrive[0]; //周轉時間=完成時間-到達時間
dqzhou[0]=zhou[0]/runtime[0]; //帶權周轉時間=周轉時間/服務時間
averagezhou=zhou[0];
average_zhou=dqzhou[0];
end[now]=1; //執行完的進程設置為1;
for(int i=1;i<n;i++)
{
int j;
for(j=1;j<n;)
{
if(arrive[j]<endtime[now]||arrive[j]==endtime[now])
j++;
else
break;
}
temp=j;
int min=p;
for(j=1;j<=temp;j++)
{
if(runtime[min]>runtime[j] && end[j]==0)
min=j;
}
next=min;
endtime[next]=endtime[now]+runtime[next];
zhou[next]=endtime[next]-arrive[next];
dqzhou[next]=zhou[next]/runtime[next];
averagezhou+=zhou[next];
average_zhou+=dqzhou[next];
end[next]=1;
now=next;
next=p;
while(end[p]!=0)
p++;
}
averagezhou=averagezhou/n;
average_zhou=average_zhou/n;
cout<<"完成時間為:"<<endl;
for(int j=0;j<n;j++)
cout<<endtime[j]<<" "<<endl;
cout<<"周轉時間為:"<<endl;
for(k=0;k<n;k++)
cout<<zhou[k]<<" "<<endl;
cout<<"帶權周轉時間為:"<<endl;
for(int m=0;m<n;m++)
cout<<dqzhou[m]<<" "<<endl;
cout<<"平均周轉時間為:"<<endl;
cout<<averagezhou<<" "<<endl;
cout<<"平均帶權周轉時間為:"<<endl;
cout<<average_zhou<<" "<<endl;
}
int EDF() //最早截止時間的調度演算法
{
int arrive_A,arrive_B; //標記進程A,進程B的到達時間
int zhouqi_A,zhouqi_B,serve_A,serve_B; //進程的周期時間和服務時間
int i,j,a=0,b=0,ka=0,kb=0; //ka,kb為開關,i,j,a,b為進程下標
int num_a=0,num_b=0; //服務累計時間
printf("輸入進程A的周期時間,服務時間: ");
scanf("%d%d",&zhouqi_A,&serve_A);
printf("輸入進程B的周期時間,服務時間: ");
scanf("%d%d",&zhouqi_B,&serve_B);
for(int T=0;T<=100;T++)
{
if(num_a==serve_A) //進程A完成
{
num_a=serve_A+1;
printf("當T=%d時",T);
printf("進程A%d結束\n",a);
if(num_b<serve_B)
{
printf(" 調用進程B%d\n",b);
kb=1;
}
ka=0;
}
if(num_b==serve_B)
{
num_b=serve_B+1;
printf("當T=%d時",T);
printf("進程B%d結束\n",b);
if(num_a<serve_A)
{
printf(" 調用進程A%d\n",a);
ka=1;
}
kb=0;
}
if(T%zhouqi_A==0 && T%zhouqi_B==0)
{
arrive_A=arrive_B=T;
j=++a;
i=++b;
printf("當T=%d時,進程A%d和進程B%d同時產生,此時,",T,j,i);
if(zhouqi_A<=zhouqi_B)
{
printf("調用進程A%d,阻塞進程B%d\n",j,i);
ka=1;
kb=0;
}
else
{
printf("調用進程B%d,阻塞進程A%d\n",i,j);
ka=0;
kb=1;
}
num_a=num_b=0;
}
if(T%zhouqi_A==0&&T%zhouqi_B!=0)
{
arrive_A=T;
printf("當T=%d時",T);
printf("進程A%d產生 ",++a); //不可能與進程A競爭處理器
num_a=0;
if(num_b<serve_B) //進程B沒有完成
if(arrive_B+zhouqi_B>arrive_A+zhouqi_A) //若進程B最早截止時間大於進程A的,則執行進程A
{
printf("進程A%d執行。\n",a);
ka=1;
kb=0;
}
else //若進程B最早截止時間小於等於進程A的
printf("進程B%d繼續執行。\n",b);
else //進程B完成
{
printf("進程A%d執行。\n",a);
ka=1;
}
}
if(T%zhouqi_A!=0 && T%zhouqi_B==0)
{
arrive_B=T;
printf("當T=%d時",T);
printf("進程B%d產生,",++b); //不可能與進程B競爭處理器
num_b=0;
if(num_a<serve_A) //進程A沒有完成
if(arrive_B+zhouqi_B>=arrive_A+zhouqi_A) //進程A的最早截止時間不小於B
printf("進程A%d繼續執行。\n",a);
else
{
printf("進程B%d執行。\n",b);
kb=1;
ka=0;
}
else //進程A完成
{
printf("進程B%d執行。\n",b);
kb=1;
}
}
if(ka)
num_a++;
if(kb)
num_b++;
}
return 1;
}
int main()
{
system("color 0b"); //設置顏色
cout<<"最早截止時間的調度演算法如下: "<<endl<<endl;
EDF();
int n;
cout<<endl;
cout<<"請輸入進程的數目: ";
cin>>n;
cout<<"請按進程到達時間從小到大依次輸入n個進程的到達時間: "<<endl;
for(int i=0;i<n;i++)
cin>>arrive[i];
cout<<"請按上面進程的順序依次輸入n個進程的服務時間: "<<endl;
for(int j=0;j<n;j++)
cin>>runtime[j];
cout<<"先來先服務調度演算法如下: "<<endl;
FCFS(arrive,runtime,n);
cout<<endl<<endl;
cout<<"短作業優先調度演算法如下: "<<endl;
SJF(arrive,runtime,n);
cout<<endl<<endl;
printf("輪轉調度演算法如下:\n\n");
printf("輸入創建進程的數目:\n");
scanf("%d",&N);
create();
RR();
return 0;
}