目錄
1 先來先服務(FCFS)
1.1 算法描述
先來先服務調度算法描述:按照進程進入的先後次序來分配處理器。先進入就緒隊列的進程優先被挑選,運行進程一旦佔有處理器將一直運行下去,直到運行結束或被阻塞,這是非搶佔式調度。
1.2 實驗內容
編寫並調試一個模擬的進程調度程序,採用 “先來先服務”調度算法對多個進程進行調度。
計算平均週轉時間和平均帶權週轉時間。
施行FCFS調度算法:
平均進程週轉時間T = (20+30+30+35)/4 = 28.75
平均帶權進程週轉時間W = (20/20+30/15+30/5+35/10)/4 = 3.125
1.3 代碼實現
//先來先服務
#include <stdlib.h>
#include <stdio.h>
struct pcb{ // 定義一個結構體,裏面包含的有一個進程相關的信息
char name[10]; //進程名稱 (輸入)
float arrivetime; //到達時間 (輸入)
float servicetime; //服務時間 (輸入)
float starttime; //開始時間
float finishtime; //結束時間
float zztime; //週轉時間=finishtime-arrivetime
float dqzztime; //帶權週轉時間=zztime/servicetime
};
//輸入進程信息
void input(pcb *p, int N) //p爲pdb數組名, N爲pcb數組的元素個數
{
int i;
printf("\n");
printf("請輸入進程的名字 到達時間 服務時間: (例如: 進程1 0 100)\n");
for(i=0; i<=N-1; i++)
{
printf("請輸入進程%d的信息:", i+1); // i=0時,輸入第1個進程相關信息
scanf("%s", &p[i].name);
scanf("%f", &p[i].arrivetime);
scanf("%f", &p[i].servicetime);
}
}
//排序: 按照進程的arrivetime(從小到大)對pcb數組中的N個進程進行排序
void sort(pcb *p, int N)
{
for(int i=0; i < N-1; i++)
{
for(int j=i+1; j<N; j++)
{
if(p[i].arrivetime > p[j].arrivetime)
{
pcb temp;
temp=p[i];
p[i]=p[j];
p[j]=temp;
}
}
}
}
//運行
void run(pcb *p, int N)
{
int k;
for(k=0; k<=N-1; k++)
{
if(k==0) //第1個進程
{
p[k].starttime = p[k].arrivetime; //第1個進程到達之後即可執行
p[k].finishtime = p[k].starttime + p[k].servicetime;
}
else
{
p[k].starttime = (p[k-1].finishtime >= p[k].arrivetime)? p[k-1].finishtime: p[k].arrivetime;
p[k].finishtime = p[k].starttime + p[k].servicetime;
}
}
for(k=0; k<=N-1; k++)
{
p[k].zztime = p[k].finishtime - p[k].arrivetime;
p[k].dqzztime = p[k].zztime / p[k].servicetime;
}
}
//顯示
void Print(pcb*p, int N)
{
int k;
printf("調用先來先服務算法以後進程運行的順序是: ");
printf("%s", p[0].name); //首先運行第一個進程p[0]
for(k=1; k<N; k++)
{
printf("-->");
printf("%s", p[k].name); //輸出 -->p[k].name
}
printf("\n");
printf("具體進程調度信息:\n");
printf("進程名 到達時間 服務時間 開始時間 結束時間 週轉時間 帶權週轉時間\n");
for(k=0; k<=N-1; k++)
{
printf("%4s", p[k].name);
printf("%10.3f", p[k].arrivetime);
printf("%10.3f", p[k].servicetime);
printf("%10.3f", p[k].starttime);
printf("%10.3f", p[k].finishtime);
printf("%10.3f", p[k].zztime);
printf("%10.3f\n", p[k].dqzztime);
}
}
//先來先服務算法FCFS
void FCFS(pcb *p,int N)
{
sort(p,N);
run(p, N);
Print(p, N);
int k;
float Attime = 0; //平均週轉時間
float AQttime = 0; //平均帶權週轉時間
for(k=0; k<=N-1; k++)
{
Attime += p[k].zztime;
AQttime += p[k].dqzztime;
}
Attime = Attime / N;
AQttime = AQttime / N;
printf("調用先來先服務算法的平均週轉時間爲:");
printf("%.3f\n", Attime);
printf("調用先來先服務算法的平均帶權週轉時間爲:");
printf("%.3f\n", AQttime);
}
int main( )
{
pcb a[100]; //a爲pcb數組 a[0]~a[N-1]對象第1個進程到第N個進程的信息
int N; //N爲進程數目
printf("\n");
printf("\n");
printf("<<----------!!!@@@先來先服務調度算法@@@!!!---------->>");
printf("\n");
printf("輸入進程數目:");
scanf("%d", &N);
input(a, N); //a是pcb數組名,N是實際使用數組元素個數
FCFS(a, N); //fcfs模擬調度
return 0;
}
代碼運行結果截圖
2. 短進程優先(非搶佔和搶佔)算法(SPF)
2.1 算法描述
短進程優先算法描述:每次選出最短的進程進行調度,調度完畢則淘汰,直到所有進程都調度完畢。
編寫並調試一個模擬的進程調度程序,採用 “短進程優先”調度算法對多個進程進行調度。
計算平均週轉時間和平均帶權週轉時間。
2.2 實驗內容
施行SPF(非搶佔式)算法:
SPF的進程調度順序爲進程1、3、4、2,
平均進程週轉時間T = (20+15+20+45)/4 = 25
平均帶權進程週轉時間W = (20/20+15/5+20/10+45/15)/4 = 2.25
2.3 代碼實現
//短進程優先調度算法
#include <stdlib.h>
#include <stdio.h>
//定義一個結構體:PCB
struct pcb{
char name[10];
float arrivetime;
float servicetime;
float starttime;
float finishtime;
float zztime;
float dqzztime;
};
//***輸入進程信息,將N個進程的信息寫入pcb型數組***
void input(pcb *p,int N)
{
int i;
printf("\n");
printf("請輸入進程的名字 到達時間 服務時間: (例如: a 0 100)\n");
for(i=0; i <= N-1; i++)
{
printf("請輸入進程%d的信息:", i+1);
scanf("%s", &p[i].name);
scanf("%f", &p[i].arrivetime);
scanf("%f", &p[i].servicetime);
}
}
//***優先級排序***
void sort(pcb *p, int N)
{
/*
1、對pcb型數組中的元素進行一個簡單的排序
找到優先級最高的進程
並把其他進程也進行簡單排序,方便後續工作
*/
//排序: N次循環,每次找到從i到N-1中優先級最高的進程,放到p[i]
for(int i=0;i<=N-1;i++)
{
//循環比較剩餘的變量 //排序後:從0~N-1 arrivetime增加 , arrivetime相同時, servicetime短的優先
for(int j=i+1;j<N;j++)
{
if(p[i].arrivetime>p[j].arrivetime || (p[i].arrivetime==p[j].arrivetime && p[i].servicetime>p[j].servicetime) )
{
//p[j]的優先級高於p[i],因此把p[j]放到p[i]
pcb temp;
temp = p[i];
p[i] = p[j];
p[j] = temp;
}
}
}
/*
2、每個進程運行完成之後,找到當前時刻已經到達的最短進程
P[0]優先級最高,p[0].finishtime=p[0].arrivetime+p[0].servicetime
m!=0時:p[m].finishtime=p[m-1].finishtime+p[m].servicetime
*/
for(int m=0; m<N-1; m++)
{
if(m == 0)
p[m].finishtime = p[m].arrivetime + p[m].servicetime;
else
p[m].finishtime = ((p[m-1].finishtime >= p[m].arrivetime)? p[m-1].finishtime: p[m].arrivetime) + p[m].servicetime;
//(1)找到p[m].finishtime時刻哪些進程已經到達
int i=0; //i統計 p[m].finishtime時刻有幾個進程已經到達
//從下一個進程p[m+1]開始尋找
for(int n = m+1; n <= N-1; n++)
{
if(p[n].arrivetime <= p[m].finishtime)
i++;
else
break;
/*由於在第1步已經對進程按照到達時間進行了排序
故:當p[n].arrivetime > p[m].finishtime時,
說明p[n]進程和其後面的其他進程都未到達。
i的值爲p[m].finishtime時刻已經到達的進程數目。
*/
}
//(2)找到p[m].finishtime時刻已經到達的最短進程
float min = p[m+1].servicetime; //next進程服務時間爲p[m+1].servicetime (初值)
int next = m+1; //next進程爲m+1 (初值)
//p[m+1]至p[m+i]這i個已到達進程中找到最短進程
for(int k = m+1; k < m+i; k++) //k爲m+1 ~ m+i-1
{
//min的初值是p[m+1].servicetime, k+1爲m+2 ~m+i
if(p[k+1].servicetime < min)
{
min = p[k+1].servicetime;
next = k+1;
}
}
//(3)把最短進程放在p[m+1]進程處
pcb temp;
temp=p[m+1];
p[m+1]=p[next];
p[next]=temp;
}
}
//***運行***
void run(pcb *p, int N)
{
int k;
//計算各進程的開始時間和結束時間
for(k=0; k <= N-1; k++)
{
if(k==0) //第1個進程
{
p[k].starttime = p[k].arrivetime; //第1個進程到達之後即可執行
p[k].finishtime = p[k].starttime + p[k].servicetime;
}
else
{
p[k].starttime = (p[k-1].finishtime >= p[k].arrivetime)? p[k-1].finishtime: p[k].arrivetime;
p[k].finishtime = p[k].starttime + p[k].servicetime;
}
}
//計算各進程的週轉時間和帶權週轉時間
for(k=0; k<=N-1; k++)
{
p[k].zztime = p[k].finishtime - p[k].arrivetime;
p[k].dqzztime = p[k].zztime / p[k].servicetime;
}
}
//***顯示***
void Print(pcb *p, int N)
{
int k;
printf("調用最短進程優先算法以後進程運行的順序是: ");
printf("%s",p[0].name);
for(k=1;k<N;k++)
{
printf("-->");
printf("%s", p[k].name);
}
printf("\n");
printf("具體進程調度信息:\n");
printf("進程名 到達時間 服務時間 開始時間 結束時間 週轉時間 帶權週轉時間\n");
for(k=0; k<=N-1; k++)
{
printf("%4s", p[k].name);
//%m.nf:輸出共佔m列,其中有n位小數,如數值寬度小於m左端補空格
printf("%10.3f", p[k].arrivetime);
printf("%10.3f", p[k].servicetime);
printf("%10.3f", p[k].starttime);
printf("%10.3f", p[k].finishtime);
printf("%10.3f", p[k].zztime);
printf("%10.3f\n", p[k].dqzztime);
}
}
//***短進程優先***
void sjff(pcb *p,int N)
{
sort(p, N);
run(p, N);
Print(p, N);
int k;
float Attime = 0; // 平均週轉時間
float AQttime = 0; //平均帶權週轉時間
for(k=0; k<=N-1; k++)
{
Attime += p[k].zztime;
AQttime += p[k].dqzztime;
}
Attime = Attime/N;
AQttime = AQttime/N;
printf("調用短進程優先算法的平均週轉時間爲:");
printf("%.3f\n", Attime);
printf("調用短進程優先算法的平均帶權週轉時間爲:");
printf("%.3f\n", AQttime);
}
//***主函數***
int main()
{
//定義一個pcb型數組a
pcb a[100];
int N; //進程數目
printf("\n");
printf("\n");
printf("<<----------******短進程優先調度算法******---------->>");
printf("\n");
printf("輸入進程數目:");
scanf("%d", &N);
input(a, N);
sjff(a, N);
return 0;
}
代碼運行結果截圖