標籤:
一、目的和要求
1. 實驗目的
(1)加深對作業調度演算法的理解;
(2)進行程式設計的訓練。
2.實驗要求
用進階語言編寫一個或多個作業調度的類比程式。
單道批處理系統的作業發送器。作業一投入運行,它就佔有電腦的一切資源直到作業完成為止,因此調度作業時不必考慮它所需要的資源是否得到滿足,它所啟動並執行時間等因素。
作業調度演算法:
1) 採用先來先服務(FCFS)調度演算法,即按作業到達的先後次序進行調度。總是首先調度在系統中等待時間最長的作業。
2) 短作業優先 (SJF) 調度演算法,優先調度要求已耗用時間最短的作業。
3) 響應比高者優先(HRRN)調度演算法,為每個作業設定一個優先權(響應比),調度之前先計算各作業的優先權,優先數高者優先調度。RP (響應比)= 作業周轉時間 / 作業已耗用時間=1+作業等待時間/作業已耗用時間
每個作業由一個作業控制塊JCB表示,JCB可以包含以下資訊:作業名、提交(到達)時間、所需的已耗用時間、所需的資源、作業狀態、鏈指標等等。
作業的狀態可以是等待W(Wait)、運行R(Run)和完成F(Finish)三種之一。每個作業的最初狀態都是等待W。
一、 類比資料的產生
1. 允許使用者指定作業的個數(2-24),預設值為5。
2. 允許使用者選擇輸入每個作業的到達時間和所需已耗用時間。
3. (**)從檔案中讀入以上資料。
4. (**)也允許使用者選擇通過偽隨機數指定每個作業的到達時間(0-30)和所需已耗用時間(1-8)。
二、 類比程式的功能
1. 按照類比資料的到達時間和所需已耗用時間,執行FCFS, SJF和HRRN調度演算法,程式計算各作業的開始執行時間,各作業的完成時間,周轉時間和帶權周轉時間(周轉係數)。
2. 動態示範每調度一次,更新現在系統時刻,處於運行狀態和等待各作業的相應資訊(作業名、到達時間、所需的已耗用時間等)對於HRRN演算法,能在每次調度時顯示各作業的響應比R情況。
3. (**)允許使用者在類比過程中提交新作業。
4. (**)編寫並調度一個多道程式系統的作業調度類比程式。 只要求作業調度演算法:採用基於先來先服務的調度演算法。 對於多道程式系統,要假定系統中具有的各種資源及數量、調度作業時必須考慮到每個作業的資源要求。
三、 類比資料結果分析
1. 對同一個類比資料各演算法的平均周轉時間,周轉係數比較。
2. (**)用曲線圖或直條圖表示出以上資料,分析演算法的優點和缺點。
四、 實驗準備
|
序號 |
準備內容 |
完成情況 |
|
1 |
什麼是作業? |
|
|
2 |
一個作業具備什麼資訊? |
|
|
3 |
為了方便類比調度過程,作業使用什麼方式的資料結構存放和表示?JCB |
|
|
4 |
作業系統中,常用的作業調度演算法有哪些? |
|
|
5 |
如何編程實現作業調度演算法? |
|
|
6 |
類比程式的輸入如何設計更方便、結果輸出如何呈現更好? |
|
五、 其他要求
1. 完成報告書,內容完整,規格規範。
2. 實驗須檢查,回答實驗相關問題。
註:帶**號的條目表示選做內容。
二、實驗內容
根據指定的實驗課題,完成設計、編碼和調試工作,完成實驗報告。
三、實驗環境
可以採用TC,也可以選用Windows下的利用各種控制項較為方便的VB,VC等可視化環境。也可以自主選擇其他實驗環境。
四、實驗原理及核心演算法參考程式段
單道FCFS演算法:
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#define getpch(type) (type*)malloc(sizeof(type))
#define NULL 0
int n;
float T1=0,T2=0;
int times=0;
struct jcb //作業控制塊
{
char name[10]; //作業名
int reachtime; //作業到達時間
int starttime; //作業開始時間
int needtime; //作業需要啟動並執行時間
float super; //作業的響應比
int finishtime; //作業完成時間
float cycletime; //作業周轉時間
float cltime; //作業帶權周轉時間
char state; //作業狀態
struct jcb *next; //結構體指標
}*ready=NULL,*p,*q;
typedef struct jcb JCB;
void inital() //建立作業控制塊隊列,先將其排成先來先服務的模式隊列
{
int i;
printf("\n輸入作業數:");
scanf("%d",&n);
for(i=0;i<n;i++)
{
p=getpch(JCB);
printf("輸入作業名:");
scanf("%s",p->name);
getch();
p->reachtime=i;
printf("作業預設到達時間:%d",i);
printf("\n輸入作業需已耗用時間:");
scanf("%d",&p->needtime);
p->state=‘W‘;
p->next=NULL;
if(ready==NULL) ready=q=p;
else{
q->next=p;
q=p;
}
}
}
void disp(JCB* q,int m) //顯示作業運行後的周轉時間及帶權周轉時間等
{
if(m==3) //顯示高響應比演算法調度作業後的運行情況
{
printf("\n作業%s正在運行,估計其運行情況:\n",q->name);
printf("\n作業名 \t 作業需已耗用時間\n",q->name,p->needtime);
printf("\n 開始運行時刻 \t 完成時刻 \t 周轉時間 \t 帶權周轉時間 \t相應比 \n");
printf(" %d \t",q->starttime);
printf(" %d \t",q->finishtime);
printf(" %f \t",q->cycletime);
printf(" %f\t",q->cltime);
printf(" %f\n",q->super);
getch();
}
else // 顯示先來先服務,最短作業優先演算法調度後作業的運行情況
{
printf("\n作業%s正在運行,估計其運行情況:\n",q->name);
printf("\n 開始運行時刻 \t 完成時刻 \t 周轉時間 \t 帶權周轉時間 \n");
printf(" %d \t",q->starttime);
printf(" %d \t",q->finishtime);
printf(" %f \t",q->cycletime);
printf(" %f\t",q->cltime);
getch();
}
}
void running(JCB *p,int m) //運行作業
{
if(p==ready) //先將要啟動並執行作業從隊列中分離出來
{
ready=p->next;
p->next=NULL;
}
else
{
q=ready;
while(q->next!=p)
q=q->next;
q->next=p->next;
}
p->starttime=times;//計算作業運行後的完成時間,周轉時間等等
p->state=‘R‘;
p->finishtime=p->starttime+p->needtime;
p->cycletime=(float)(p->finishtime-p->reachtime);
p->cltime=(float)(p->cycletime/p->needtime);
T1+=p->cycletime;
T2+=p->cltime;
disp(p,m); //調用disp()函數,顯示作業運行情況
times+=p->needtime;
p->state=‘F‘;
printf("\n%s 作業已完成!\n請按任意鍵繼續...\n",p->name);
free(p); //釋放運行後的作業
getch();
}
void super() //計算隊列中作業的高響應比
{
JCB *padv;
padv=ready;
do{
if(padv->state==‘W‘&&padv->reachtime<=times)
padv->super=(float)(times-padv->reachtime+padv->needtime)/padv->needtime;
padv=padv->next;
}while(padv!=NULL);
}
void final() //最後列印工作的平均周轉時間,平均帶權周轉時間
{
float s,t;
t=T1/n; //計算平均周轉時間
s=T2/n; //計算平均帶權周轉時間
getch();
printf("\n\n作業已經全部完成!");
printf("\n%d個作業的平均周轉時間是:%f",n,t);
printf("\n%d個作業的平均帶權周轉時間是:%f\n\n\n",n,s);
}
void hrn(int m) //高響應比演算法
{
JCB *min;
int i,iden;
system("cls"); //調用系統命令,清屏
inital();
for(i=0;i<n;i++)
{
p=min=ready;
iden=1;
super();
do{
if(p->state==‘W‘&&p->reachtime<=times)
if(iden)
{
min=p;
iden=0;
}
else if(p->super>min->super)
min=p;
p=p->next;
}while(p!=NULL);
if(iden)
{
i--;
times++;
if(times>1000)
{
printf("\nruntime is too long...error...");
getch();
}
}
else
{
running(min,m); //調用running()函數
}
}
final(); //調用running()函數
}
void sjf(int m) // 最短作業優先演算法
{
JCB *min;
int i,iden;
system("cls");
inital();
for(i=0;i<n;i++)
{
p=min=ready;
iden=1;
do{
if(p->state==‘W‘&&p->reachtime<=times)
if(iden)
{
min=p;iden=0;
}
else if(p->needtime<min->needtime)
min=p;
p=p->next;
}while(p!=NULL);
if(iden)
{
i--;
times++;
if(times>100){printf("\nruntime is too long...error");
getch();
}
}
else{
running(min,m); //調用running()函數
}
}
final(); //調用running()函數
}
void fcfs(int m) //先來先服務演算法
{
int i,iden;
system("cls");
inital();
for(i=0;i<n;i++)
{
p=ready;
iden=1;
do{
if(p->state==‘W‘&&p->reachtime<=times)
iden=0;
if(iden)p=p->next;
}while(p!=NULL&&iden);
if(iden)
{
i--;
printf("\n沒有滿足要求的進程,需等待");
times++;
if(times>100){printf("\n時間過長");
getch();
}
}
else{
running(p,m); //調用running()函數
}
}
final(); //調用running()函數
}
void mune()
{
int m;
system("cls");
printf("\n\n\t\t*********************************************\t\t\n");
printf("\t\t*\t\t作業調度主菜單\t\t *\n");
printf("\t\t*********************************************\t\t\n");
printf("\n\n\t\t*********************************************\t\t");
printf("\n\t\t*\t1.先來先服務演算法\t\t *");
printf("\n\t\t*\t2.最短作業優先演算法\t\t *");
printf("\n\t\t*\t3.響應比高者優先演算法\t\t *");
printf("\n\t\t*\t0.退出程式\t\t\t *");
printf("\n\t\t*********************************************\t\t\n");
printf("\n\t\t\t\t選擇演算法:");
scanf("%d",&m);
switch(m)
{
case 1:
fcfs(m);
getch();
system("cls");
mune();
break;
case 2:
sjf(m);
getch();
system("cls");
mune();
break;
case 3:
hrn(m);
getch();
system("cls");
mune();
break;
case 0:
system("cls");
break;
default:
printf("選擇錯誤,重新選擇.");
getch();
system("cls");
mune();
}
}
main() //主函數
{
mune();
return 0;
}
實驗二作業調度類比程式