先來先服務、短進程優先算法
一.目的
通過使用c對先來先服務、短進程優先算法的實現,進一步理解並掌握調度算法的邏輯過程,以及每種算法分別在進程調度和作業調度中的的處理方法.
二.原理
先來先服務:該算法在每次調度中,都是從后備作業隊列中選擇一個或多個最先進入該隊列的作業,將它們調入內存,為他們分配資源、創建進程,然后放入就緒隊列。在進程調度中采用FCFS算法時,則每次調度是從就緒隊列中選擇一個最先進入該隊列的進程,位置分配處理機,使之投入運行。該進程一直運行到完成或發生某事件而阻塞后才放棄處理機。
短進程優先:該調度算法是從后備序列中選擇一個或若干個估計運行時間最短的作業,將他們調入內存運行。
三.流程圖
四.程序清單
#define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h> #include<stdlib.h> #include<string.h> #include<conio.h> #define getpch(type) (type*)malloc(sizeof(type)) int n; float T1=0,T2=0; int times=0; struct jcb //作業控制塊 { char name[10]; //作業名 int reachtime; //作業到達時間 int starttime; //作業開始時間 int needtime; //作業需要運行的時間 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("\n輸入作業名:"); scanf("%s", p->name); getchar(); 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) //顯示作業運行后的周轉時間及帶權周轉時間等 { printf("\n作業%s正在運行,估計其運行情況:\n",q->name); printf("開始運行時刻:%d\n",q->starttime); printf("完成時刻:%d\n",q->finishtime); printf("周轉時間:%f\n",q->cycletime); printf("帶權周轉時間:%f\n",q->cltime); getchar(); } 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 has been finished!\n", p->name); free(p); //釋放運行后的作業 getchar(); } void final() //最后打印作業的平均周轉時間,平均帶權周轉時間 { float s,t; t=T1/n; s=T2/n; getchar(); printf("\n\n作業已經全部完成!\n"); printf("\n%d個作業的平均周轉時間是:%f",n,t); printf("\n%d個作業的平均帶權周轉時間是%f:\n\n\n",n,s); } 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"); getchar(); } } else { running(min, m); } } final(); } 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時間過長"); getchar(); } } else { running(p, m); } } final(); } void menu() { int m; system("cls");
printf("\n\n\t\t*********************************************\t\t\n"); printf("\t\t\t\t作業調度演示\n"); printf("\t\t*********************************************\t\t\n"); printf("\n\n\n\t\t\t1.先來先服務算法."); printf("\n\t\t\t2.最短作業優先算法."); printf("\n\t\t\t0.退出程序."); printf("\n\n\t\t\t\t選擇所要操作:"); scanf("%d", &m); switch (m) { case 1: fcfs(m); getchar(); system("cls"); break; case 2: sjf(m); getchar(); system("cls"); break; case 0: system("cls"); break; default: printf("選擇錯誤,重新選擇."); getchar(); system("cls"); menu(); } } int main() { menu(); system("pause"); return 0; }
五.結果截圖
1.先來先服務算法:
2.短作業優先算法:
六.結果分析
先來先服務算法比較有利於長作業,而不利於短作業。根據先來先服務的實驗,短作業C的帶權周轉時間竟高達100,這是不能容忍的;而長作業D的帶權周轉時間僅為1.99。就此可知,先來先服務算法有利於CPU繁忙型作業,而不利於I/O繁忙型作業。
根據測試結果得知,短作業優先調度算法能有效的降低作業的平均等待時間,提高吞吐量。但同時,該算法對長作業不利,更嚴重的是,如果有一長作業進入系統的后備隊列,由於調度程序總是優先調度那些短作業,將導致長作業長期不被調度。該算法完全未考慮作業的緊迫程度,因而不能保證緊迫性作業會被及時處理。