實驗原理
(1)定義程序控制塊的結構體和程序工作時間的結構體,JCB可以包含以下信息:作業名、提交(到達)時間、所需的運行時間、所需的資源、作業狀態、鏈指針等等。程序工作時間包括作業運行時刻,作業完成時刻,周轉時間,帶權周轉時間。
(2)主程序默認采用的算法是先來先服務,當選擇另外兩種算法時通過主程序去調用這種作業調度算法,分別是SJF,HRN。
(3)通過構造進程輸入input(),進程運行結果輸出output(),disp(),以及使整個程序正常運行的函數塊等,通過主函數調用方法函數的想法來實現作業調度。
(4)在對程序控制塊的訪問和調用通過鏈表指針的形式,進行調用各種作業調度算法。在作業輸入后,會顯示輸入的內容,並把每一個作業運行的狀態都能在程序中體現出來。
1 #include<stdio.h> 2 #include <stdlib.h> 3 #include <conio.h> 4 #define getpch(type) (type*)malloc(sizeof(type)) //為進程創建一個空間 5 6 struct worktime{ 7 float Tb; //作業運行時刻 8 float Tc; //作業完成時刻 9 float Ti; //周轉時間 10 float Wi; //帶權周轉時間 11 }; 12 13 struct jcb { 14 char name[10]; //作業名 15 float arrivetime; //作業到達時間 16 float runtime; //作業所需的運行時間 17 char resource; //所需資源 18 float Rp; //后備作業響應比 19 char state; //作業狀態 20 int worked_time; //已運行時間 21 struct worktime wt; 22 int need_time; //需要運行的時間 23 int flag; //進程結束標志 24 struct jcb* link; //鏈指針 25 }*ready=NULL,*p; 26 27 typedef struct jcb JCB;//重命名結構體 28 float T=0; 29 int N; 30 JCB *front,*rear; 31 32 void sort() 33 { 34 JCB *first, *second; 35 int insert=0; //插入數 36 if((ready==NULL)||((p->arrivetime)<(ready->arrivetime))) 37 { 38 p->link=ready; 39 ready=p; 40 T=p->arrivetime; 41 p->Rp=1; 42 } 43 else 44 { 45 first=ready; 46 second=first->link; 47 while(second!=NULL) 48 { 49 if((p->arrivetime)<(second->arrivetime)) 50 { 51 p->link=second; 52 first->link=p; 53 second=NULL; 54 insert=1; 55 } 56 else 57 { 58 first=first->link; 59 second=second->link; 60 } 61 } 62 if (insert==0) first->link=p; 63 } 64 } 65 66 void SJFget() 67 { 68 JCB *front,*mintime,*rear; 69 int ipmove=0; 70 mintime=ready; 71 rear=mintime->link; 72 while(rear!=NULL) 73 { 74 if ((rear!=NULL)&&(T>=rear->arrivetime)&&(mintime->runtime)>(rear->runtime)) 75 { 76 front=mintime; 77 mintime=rear; 78 rear=rear->link; 79 ipmove=1; 80 } 81 else 82 rear=rear->link; 83 } 84 if (ipmove==1) 85 { 86 front->link=mintime->link; 87 mintime->link=ready; 88 } 89 ready=mintime; 90 } 91 92 void HRNget() 93 { 94 JCB *front,*mintime,*rear; 95 int ipmove=0; 96 mintime=ready; 97 rear=mintime->link; 98 while(rear!=NULL) 99 if ((rear!=NULL)&&(T>=rear->arrivetime)&&(mintime->Rp)<(rear->Rp)) 100 { 101 front=mintime; 102 mintime=rear; 103 rear=rear->link; 104 ipmove=1; 105 } 106 else 107 rear=rear->link; 108 if (ipmove==1){ 109 front->link=mintime->link; 110 mintime->link=ready; 111 } 112 ready=mintime; 113 } 114 115 void creatJCB() //為每個作業創建一個JCB並初始化形成一個循環鏈隊列 116 { 117 JCB *p,*l; 118 int i=0; 119 l = (JCB *)malloc(sizeof(JCB)); 120 printf("\n 請輸入作業的個數:"); 121 scanf("%d",&N); 122 printf("\n 作業號No.%d:\n",i); 123 printf("\n請輸入作業的名字:"); 124 scanf("%s",l->name); 125 printf("\n請輸入作業需要運行的時間:"); 126 scanf("%d",&l->need_time); 127 l->state = 'r'; //作業初始狀態為就緒(即准備狀態) 128 l->worked_time = 0; 129 l->link=NULL; 130 l->flag=0; 131 front=l; 132 for(i =1;i<N;i++) 133 { 134 p = (JCB *)malloc(sizeof(JCB)); 135 printf("\n 作業號No.%d:\n",i); 136 printf("\n請輸入作業的名字:"); 137 scanf("%s",p->name); 138 printf("\n請輸入作業的時間:"); 139 scanf("%d",&p->need_time); 140 p->state='r'; 141 p->worked_time=0; 142 p->flag=0; 143 l->link=p; 144 l=l->link; 145 } 146 rear=l;rear->link=front; 147 } 148 149 void output()//進程輸出函數 150 { 151 int j; 152 printf("name runtime needtime state\n"); 153 for(j=1;j<=N;j++) 154 { printf(" %-4s\t%-4d\t%-4d\t%-c\n",front->name,front->worked_time,front->need_time,front->state); 155 front=front->link; 156 } 157 printf("\n"); 158 } 159 160 int judge(JCB *p) //判斷所有進程運行結束 161 { 162 int flag=1,i; 163 for(i=0;i<N;i++) 164 { 165 if(p->state!='e') 166 { 167 flag = 0; 168 break;} 169 p=p->link; 170 } 171 return flag; 172 } 173 174 //作業輸入 175 void input() 176 { 177 int i,num; 178 printf("\n 請輸入作業的個數:"); 179 scanf("%d",&num); 180 for(i=0;i<num;i++) 181 { 182 printf(" 作業號No.%d:\n",i); 183 p=getpch(JCB); 184 printf(" 輸入作業名:"); 185 scanf("%s",p->name); 186 printf(" 輸入作業到達時刻:"); 187 scanf("%f",&p->arrivetime); 188 printf(" 輸入作業運行時間:"); 189 scanf("%f",&p->runtime); 190 printf("\n"); 191 p->state='w'; 192 p->link=NULL; 193 sort(); 194 } 195 } 196 197 int space() 198 { 199 int l=0; JCB* jr=ready; 200 while(jr!=NULL) 201 { 202 l++; 203 jr=jr->link; 204 } 205 return(l); 206 } 207 208 void disp(JCB* jr,int select) 209 { 210 if (select==3) printf("\n 作業 到達時間 服務時間 響應比 運行時刻 完成時刻 周轉時間 帶權周轉時間 \n"); 211 else printf("\n 作業 到達時間 服務時間 運行時刻 完成時刻 周轉時間 帶權周轉時間 \n"); 212 printf(" %s\t",jr->name); 213 printf("%.2f\t ",jr->arrivetime); 214 printf("%.2f\t",jr->runtime); 215 if (select==3&&p==jr) printf(" |%.2f ",jr->Rp); 216 if (p==jr){ 217 printf(" %.2f\t",jr->wt.Tb); 218 printf(" %.2f ",jr->wt.Tc); 219 printf(" %.2f\t",jr->wt.Ti); 220 printf(" %.2f",jr->wt.Wi); 221 } 222 //printf("\n"); 223 } 224 225 int destroy() 226 { 227 free(p); 228 return(1); 229 } 230 231 void check(int select) 232 { 233 JCB* jr; 234 printf(" 是 :%s",p->name);//當前執行的作業是 235 disp(p,select); 236 jr=ready; 237 destroy(); 238 } 239 240 void running(JCB* jr) 241 { 242 if (T>=jr->arrivetime) jr->wt.Tb=T; 243 else jr->wt.Tb=jr->arrivetime; 244 jr->wt.Tc=jr->wt.Tb+jr->runtime; 245 jr->wt.Ti=jr->wt.Tc-jr->arrivetime; 246 jr->wt.Wi=jr->wt.Ti/jr->runtime; 247 T=jr->wt.Tc; 248 } 249 250 int main() 251 { 252 int select=0,len,h=0; 253 float sumTi=0,sumWi=0; 254 printf("請選擇作業調度算法的方式:\n"); 255 printf("\t1.FCFS 2.SJF 3.HRN \n"); 256 printf("請輸入作業調度算法序號(1-3):"); 257 scanf("%d",&select); 258 259 input(); //調用輸入函數 260 len=space(); 261 262 263 while((len!=0)&&(ready!=NULL)) 264 { 265 h++; 266 printf(" 第%d個執行作業 ",h); 267 p=ready; 268 ready=p->link; 269 p->link=NULL; 270 p->state='R'; 271 running(p); 272 sumTi+=p->wt.Ti; 273 sumWi+=p->wt.Wi; 274 check(select); //與所選擇的算法比較,調用void check(int select) 275 if (select==2&&h<len-1) SJFget(); 276 if (select==3&&h<len-1) HRNget(); 277 getchar(); 278 getchar(); 279 } 280 printf(" 作業已經完成.\n"); 281 printf("\t 此組作業的平均周轉時間:%.2f\n",sumTi/h); 282 printf("\t 此組作業的帶權平均周轉時間:%.2f\n",sumWi/h); 283 getchar(); 284 }
程序運行結果 FCFS
SJF
HRRN
總結與體會
通過本次實驗,感覺自己對之前數據結構的算法和語法掌握得不是很好,雖然會定義結構體比較熟練,但是對於在程序中調用結構體就不太理解,導致多次出錯,並通過查閱相關資料,然后不斷修改,由於之前的數據結構學得不扎實,所以寫代碼遇到很多困難,往后要多回顧舊知識,特別是語法結構和新接觸的幾種作業調度的算法思想。