① 動態高優先權優先調度演算法
動態高優先權優先調度演算法:
動態優先權是指,在創建進程時所賦予的優先權,是可以隨進程的推進或隨其等待時間的增加而改變的,以便獲得更好的調度性能。例如,我們可以規定,在就緒隊列中的進程,隨其等待時間的增長,其優先權以速率a提高。若所有的進程都具有相同的優先權初值,則顯然是最先進入就緒隊列的進程,將因其動態優先權變得最高而優先獲得處理機,此即FCFS演算法。若所有的就緒進程具有各不相同的優先權初值,那麼,對於優先權初值低的進程,在等待了足夠的時間後,其優先權便可能升為最高,從而可以獲得處理機。當採用搶占式優先權調度演算法時,如果再規定當前進程的優先權以速率b下降,則可防止一個長作業長期地壟斷處理機。
演算法代碼模擬實現:
#include<stdio.h>
#include<stdlib.h>
#defineN6
//待插入就緒隊列的進程數據
intid[N]={0,1,
2,3,4,
5};
intpriority[N]={9,38,17,
2,7,18};
intcpuTime[N]={0,
0,0,0,
0,0};
intallTime[N]={3,
2,3,6,
1,3};
//********************************
//
//模擬進程/PCB數據結構
//
//********************************
//
枚舉進程的狀態:就緒、執行、阻塞、完成
enumSTATE{Ready,Run,Block,Finish
};
//建立PCB結構體
structPCB{
intid;//標志數
intpriority;//優先數
intcpuTime;//
已佔CPU時間
intallTime;//
還需佔CPU時間
intblockTime;//已被阻塞的時間
STATEstate;//
進程狀態
PCB*pre;//
PCB的前指針
PCB*nxt;//
PCB的後指針
};
//********************************
//
//模擬進程隊列
//
//********************************
//進程入列
voidqueQush(PCB*process,PCB
*queHead)
{
process->pre=NULL;
process->nxt=
queHead->nxt;
if(queHead->nxt!=NULL){
//非第一個入列
queHead->nxt->pre=
process;
}
queHead->nxt=process;
}
//進程出列
voidquePop(PCB*process,PCB
*queHead)
{
if(process->pre!=NULL){
//不是頭節點
process->pre->nxt=
process->nxt;
}
else{
queHead->nxt=
process->nxt;
}
if(process->nxt!=NULL){
//不是尾節點
process->nxt->pre=
process->pre;
}
//
清空進程指針
process->pre=process->nxt=
NULL;
}
//查看隊列里進程的信息
voidqueWalk(PCB*queHead)
{
PCB*pro=queHead->nxt;
if(pro==NULL){
printf("(無進程) ");
return;
}
while(pro!=NULL)
{
printf("id:%d,
pri:%d,alltime:%d ",
pro->id,
pro->priority,
pro->allTime);
pro=
pro->nxt;
}
}
//********************************
//
//模擬就緒隊列
//
//********************************
intreadyQueNum;//就緒隊列的進程數量
PCBreadyQueHead;//
就緒隊列的頭部
PCB*readyMaxProcess;//就緒隊列中優先順序最高的進程
//進程插入到就緒隊列
voidreadyQueQush(PCB
*process)
{
readyQueNum++;
process->state=Ready;
queQush(process,&readyQueHead);
}
//優先順序最高的進程出列
PCB*readyQuePop()
{
readyQueNum--;
quePop(readyMaxProcess,
&readyQueHead);
returnreadyMaxProcess;
}
//每個時間片,更新就緒隊列里進程的信息
voidreadyQueUpdate()
{
intmaxPriority=-1;
PCB*pro=readyQueHead.nxt;
if(pro==NULL){
//就緒隊列沒有進程
readyMaxProcess=
NULL;
return;
}
while(pro!=NULL)
{
pro->priority
++;
if(pro->priority>maxPriority)
{
maxPriority=
pro->priority;
readyMaxProcess=pro;
}
pro=
pro->nxt;
}
}
//返回就緒隊列最高優先順序的值
intreadyMaxPriority()
{
returnreadyMaxProcess->priority;
}
//查看就緒隊列里進程的信息
voidreadyQueWalk()
{
printf("就緒隊列里的進程信息為: ");
queWalk(&readyQueHead);
}
//********************************
//
//模擬阻塞隊列
//
//********************************
#defineEndBlockTime3
//進程最長被阻塞時間
intblockQueNum;//阻塞隊列的進程數量
PCBblockQueHead;//
阻塞隊列的頭部
PCB*blockMaxProcess;//阻塞隊列中優先順序最高的進程
//進程插入到阻塞隊列
voidblockQueQush(PCB
*process)
{
blockQueNum++;
process->blockTime=0;
process->state=Block;
queQush(process,&blockQueHead);
}
//優先順序最高的進程出列
PCB*blockQuePop()
{
blockQueNum--;
quePop(blockMaxProcess,
&blockQueHead);
returnblockMaxProcess;
}
//每個時間片,更新阻塞隊列里進程的信息
voidblockQueUpdate()
{
intmaxPriority=-1;
PCB*pro=blockQueHead.nxt;
while(pro!=NULL)
{
pro->blockTime
++;
if(pro->blockTime>=EndBlockTime)
{
PCB*process=pro;
pro=pro->nxt;
//阻塞時間到,調入就緒隊列
blockQueNum--;
quePop(process,
&blockQueHead);
readyQueQush(process);
}else
if(pro->priority>maxPriority)
{
//更新阻塞隊列里優先順序最高的進程指針
maxPriority=
pro->priority;
blockMaxProcess=pro;
pro=pro->nxt;
}
}
}
//查看阻塞隊列里進程的信息
voidblockQueWalk()
{
printf("阻塞隊列里的進程信息為: ");
queWalk(&blockQueHead);
}
//********************************
//
//模擬動態優先權的進程調度
//
//********************************
//初始化數據
voidinitData()
{
//
初始化就緒隊列和阻塞隊列
readyQueNum=blockQueNum=0;
readyMaxProcess=blockMaxProcess=NULL;
readyQueHead.pre=readyQueHead.nxt=NULL;
blockQueHead.pre=blockQueHead.nxt=NULL;
//
初始化進程進入就緒隊列
inti,maxPriority=-1;
for(i=0;i<N;i
++)
{
//分配一個PCB的內存空間
PCB*pro=(PCB
*)malloc(sizeof(PCB));
//給當前的PCB賦值
pro->id
=id[i];
pro->priority
=priority[i];
pro->cpuTime
=cpuTime[i];
pro->allTime
=allTime[i];
pro->blockTime
=0;
if(pro->allTime>0){
//插入到就緒隊列中
readyQueQush(pro);
//更新就緒隊列優先順序最高的進程指針
if(pro->priority>
maxPriority){
maxPriority=pro->priority;
readyMaxProcess=pro;
}
}
}
}
//模擬cpu執行1個時間片的操作
voidcpuWord(PCB
*cpuProcess)
{
cpuProcess->priority-=3;
if(cpuProcess->priority<0)
{
cpuProcess->priority=0;
}
cpuProcess->cpuTime++;
cpuProcess->allTime--;
//
顯示正執行進程的信息:
printf("CPU正執行的進程信息為: ");
printf("id:M,pri:M,
alltime:M ",
cpuProcess->id,
cpuProcess->priority,
cpuProcess->allTime);
}
intmain()
{
inttimeSlice=0;//
模擬時間片
intcpuBusy=0;
//模擬cpu狀態
PCB*cpuProcess=NULL;//當前在cpu執行的進程
//
初始化數據
initData();
//
模擬進程調度
while(1)
{
if(readyQueNum==0
&&blockQueNum==0
&&cpuBusy==0){
//就緒隊列、阻塞隊列和cpu無進程,退出
break;
}
//printf(" %d%d",
readyQueNum,blockQueNum);
if(cpuBusy==0)
{
//cpu空閑,選擇一個進程進入cpu
if(readyQueNum>0)
{
//
選擇緒隊列優先順序最高的進程
cpuProcess
=readyQuePop();
}else{
//
就緒隊列沒有進程,改為選擇阻塞隊列優先順序最高的進程
cpuProcess
=blockQuePop();
}
cpuProcess->cpuTime=
0;
cpuProcess->state=
Run;
cpuBusy=1;
}
timeSlice++;
printf(" 第%d個時間片後: ",
timeSlice);
//
模擬cpu執行1個時間片的操作
cpuWord(cpuProcess);
if(cpuProcess->allTime==0){
cpuProcess->state=
Finish;
//釋放已完成進程的PCB
free(cpuProcess);
cpuBusy=0;
}
//
更新就緒隊列和阻塞隊列里的進程信息
blockQueUpdate();
readyQueUpdate();
//
查看就緒隊列和阻塞隊列的進程信息
readyQueWalk();
blockQueWalk();
if(cpuBusy==1
&&readyQueNum>0
&&
cpuProcess->priority
<readyMaxPriority()){
//需搶佔cpu,當前執行的進程調入阻塞隊列
blockQueQush(cpuProcess);
cpuProcess=readyQuePop();
}
}
printf(" 模擬進程調度演算法結束 ");
return0;
}
② 最高優先權優先調度和先進先出的區別
最高優先權優先調度(Highest Priority First,HPF)是一種調度演算法,其核心思想是把所有排隊等待被執行的任務按照優先順序進行排序,並把優先順序最高的任務放到隊列的前面,依次進行調度。
先進先出(First In First Out,FIFO)是另一種調度演算法,它的核心思想是把所有排隊等待被執行的任務按照入隊的時間順序排序,先進入隊列的任務優先被調度。
兩種調度演算法都用於提高系統的資源利用率,但是它們的實現方式和優先順序判定標准不同。最高優先權優先調度演算法強調優先順序的重要性,會把優先順序最高的任務作為優先執行的對象,而先進先出演算法則主要關注時間的順序,按照先進先出的順序依次執行任務。
③ 第三章 進程調度的幾種方式
進程調度概念:操作系統必須為多個,嗎進程可能有競爭的請求分配計算機資源。對處理器而言,可分配的資源是在處理器上的執行時間,分配途徑是調度。調度功能必須設計成可以滿足多個目標,包括公平、任何進程都不會餓死、有效地使用處理器時間和低開銷。此外,調度功能可能需要為某些進程的啟動或結束考慮不同的優先順序和實時最後期限。
這些年以來,調度已經成為深入研究的焦點,並且已經實現了許多不同的演算法。如今,調度研究的重點是開發多處理系統,特別是用於多線程的。
下面簡介幾種調度演算法。
一、先來先服務和短作業(進程)優先調度演算法
1.先來先服務調度演算法
先來先服務(FCFS)調度演算法是一種最簡單的調度演算法,該演算法既可用於作業調度,也可用於進程調度。當在作業調度中採用該演算法時,每次調度都是從後備作業隊列中選擇一個或多個最先進入該隊列的作業,將它們調入內存,為它們分配資源、創建進程,然後放入就緒隊列。在進程調度中採用FCFS演算法時,則每次調度是從就緒隊列中選擇一個最先進入該隊列的進程,為之分配處理機,使之投入運行。該進程一直運行到完成或發生某事件而阻塞後才放棄處理機。
2.短作業(進程)優先調度演算法
短作業(進程)優先調度演算法SJ(P)F,是指對短作業或短進程優先調度的演算法。它們可以分別用於作業調度和進程調度。短作業優先(SJF)的調度演算法是從後備隊列中選擇一個或若干個估計運行時間最短的作業,將它們調入內存運行。而短進程優先(SPF)調度演算法則是從就緒隊列中選出一個估計運行時間最短的進程,將處理機分配給它,使它立即執行並一直執行到完成,或發生某事件而被阻塞放棄處理機時再重新調度。
二、高優先權優先調度演算法
1.優先權調度演算法的類型
為了照顧緊迫型作業,使之在進入系統後便獲得優先處理,引入了最高優先權優先(FPF)調度演算法。此演算法常被用於批處理系統中,作為作業調度演算法,也作為多種操作系統中的進程調度演算法,還可用於實時系統中。當把該演算法用於作業調度時,系統將從後備隊列中選擇若干個優先權最高的作業裝入內存。當用於進程調度時,該演算法是把處理機分配給就緒隊列中優先權最高的進程,這時,又可進一步把該演算法分成如下兩種。
1) 非搶占式優先權演算法
在這種方式下,系統一旦把處理機分配給就緒隊列中優先權最高的進程後,該進程便一直執行下去,直至完成;或因發生某事件使該進程放棄處理機時,系統方可再將處理機重新分配給另一優先權最高的進程。這種調度演算法主要用於批處理系統中;也可用於某些對實時性要求不嚴的實時系統中。
2) 搶占式優先權調度演算法
在這種方式下,系統同樣是把處理機分配給優先權最高的進程,使之執行。但在其執行期間,只要又出現了另一個其優先權更高的進程,進程調度程序就立即停止當前進程(原優先權最高的進程)的執行,重新將處理機分配給新到的優先權最高的進程。因此,在採用這種調度演算法時,是每當系統中出現一個新的就緒進程i 時,就將其優先權Pi與正在執行的進程j 的優先權Pj進行比較。如果Pi≤Pj,原進程Pj便繼續執行;但如果是Pi>Pj,則立即停止Pj的執行,做進程切換,使i 進程投入執行。顯然,這種搶占式的優先權調度演算法能更好地滿足緊迫作業的要求,故而常用於要求比較嚴格的實時系統中,以及對性能要求較高的批處理和分時系統中。
2.高響應比優先調度演算法
在批處理系統中,短作業優先演算法是一種比較好的演算法,其主要的不足之處是長作業的運行得不到保證。如果我們能為每個作業引入前面所述的動態優先權,並使作業的優先順序隨著等待時間的增加而以速率a 提高,則長作業在等待一定的時間後,必然有機會分配到處理機。該優先權的變化規律可描述為:
由於等待時間與服務時間之和就是系統對該作業的響應時間,故該優先權又相當於響應比RP。據此,又可表示為:
由上式可以看出:
(1) 如果作業的等待時間相同,則要求服務的時間愈短,其優先權愈高,因而該演算法有利於短作業。
(2) 當要求服務的時間相同時,作業的優先權決定於其等待時間,等待時間愈長,其優先權愈高,因而它實現的是先來先服務。
(3) 對於長作業,作業的優先順序可以隨等待時間的增加而提高,當其等待時間足夠長時,其優先順序便可升到很高,從而也可獲得處理機。簡言之,該演算法既照顧了短作業,又考慮了作業到達的先後次序,不會使長作業長期得不到服務。因此,該演算法實現了一種較好的折衷。當然,在利用該演算法時,每要進行調度之前,都須先做響應比的計算,這會增加系統開銷。
三、基於時間片的輪轉調度演算法
1.時間片輪轉法
1) 基本原理
在早期的時間片輪轉法中,系統將所有的就緒進程按先來先服務的原則排成一個隊列,每次調度時,把CPU 分配給隊首進程,並令其執行一個時間片。時間片的大小從幾ms 到幾百ms。當執行的時間片用完時,由一個計時器發出時鍾中斷請求,調度程序便據此信號來停止該進程的執行,並將它送往就緒隊列的末尾;然後,再把處理機分配給就緒隊列中新的隊首進程,同時也讓它執行一個時間片。這樣就可以保證就緒隊列中的所有進程在一給定的時間內均能獲得一時間片的處理機執行時間。換言之,系統能在給定的時間內響應所有用戶的請求。
2.多級反饋隊列調度演算法
前面介紹的各種用作進程調度的演算法都有一定的局限性。如短進程優先的調度演算法,僅照顧了短進程而忽略了長進程,而且如果並未指明進程的長度,則短進程優先和基於進程長度的搶占式調度演算法都將無法使用。而多級反饋隊列調度演算法則不必事先知道各種進程所需的執行時間,而且還可以滿足各種類型進程的需要,因而它是目前被公認的一種較好的進程調度演算法。在採用多級反饋隊列調度演算法的系統中,調度演算法的實施過程如下所述。
(1) 應設置多個就緒隊列,並為各個隊列賦予不同的優先順序。第一個隊列的優先順序最高,第二個隊列次之,其餘各隊列的優先權逐個降低。該演算法賦予各個隊列中進程執行時間片的大小也各不相同,在優先權愈高的隊列中,為每個進程所規定的執行時間片就愈小。例如,第二個隊列的時間片要比第一個隊列的時間片長一倍,……,第i+1個隊列的時間片要比第i個隊列的時間片長一倍。
(2) 當一個新進程進入內存後,首先將它放入第一隊列的末尾,按FCFS原則排隊等待調度。當輪到該進程執行時,如它能在該時間片內完成,便可准備撤離系統;如果它在一個時間片結束時尚未完成,調度程序便將該進程轉入第二隊列的末尾,再同樣地按FCFS原則等待調度執行;如果它在第二隊列中運行一個時間片後仍未完成,再依次將它放入第三隊列,……,如此下去,當一個長作業(進程)從第一隊列依次降到第n隊列後,在第n 隊列便採取按時間片輪轉的方式運行。
(3) 僅當第一隊列空閑時,調度程序才調度第二隊列中的進程運行;僅當第1~(i-1)隊列均空時,才會調度第i隊列中的進程運行。如果處理機正在第i隊列中為某進程服務時,又有新進程進入優先權較高的隊列(第1~(i-1)中的任何一個隊列),則此時新進程將搶占正在運行進程的處理機,即由調度程序把正在運行的進程放回到第i隊列的末尾,把處理機分配給新到的高優先權進程。