1. 程式人生 > 實用技巧 >OS-程序排程

OS-程序排程

排程演算法

  • 先來先服務

  • 優先順序排程(這裡是非搶佔)(第一個到達的肯定要先執行)

  • 短作業優先(第一個到達的肯定要先執行)

  • 時間片輪轉

時間片輪轉和先來先服務的區別就是前者也是先來先服務,但是給你三分鐘的時間片你要是幹不完一碗飯就排到最後面,等一下接著吃

實驗模擬如下

程序ID arrivetime servicetime priority
1 1 9 2
2 4 6 3
3 5 3 1
#include<stdio.h>
#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
#define max 50

struct PCB
{
	int name;
	int arrivetime; //到達時間
	int servicetime; //服務時間
    int finishtime; //完成/結束時間
    int turntime; //週轉時間
    int average_turntime; //帶權週轉時間
	int sign; //標誌程序是否完成,用於後續時間片輪轉中
	int remain_time; //剩餘時間
	int priority;  //優先順序
}pcb[max];//順便定義程序陣列pcb

void init(int n)  //初始化;這裡不使用0號位置即(程序1對應下標1);0號位作為中間容器
{   
	int i;
	for(i=1;i<=n;i++)
	{
		pcb[i].arrivetime=0; 
		pcb[i].servicetime=0;
	    pcb[i].finishtime=0; 
	    pcb[i].turntime=0;
	    pcb[i].average_turntime=0;
		pcb[i].remain_time=0;
		pcb[i].sign=0;
		pcb[i].priority=0;
	}
}
void creat(int n) //建立PCB
{
	int i;
	//若n為3,則對下標1,2,3進行設定程序PCB
	for(i=1;i<=n;i++)
	{
		printf("\n%d:\ninput the information of process\n  input processID:",i);
		scanf("%d",&pcb[i].name);
		printf("  input the arrivetime:");
		scanf("%d",&pcb[i].arrivetime);
		printf("  input the servicetime:");
		scanf("%d",&pcb[i].servicetime);
		printf("  input the priority:");
		scanf("%d",&pcb[i].priority);
		pcb[i].remain_time=pcb[i].servicetime;  //初始化剩餘時間為服務時間
	}
}

void FCFS(int n) //先來先服務
{
	int starttime;
	//先設定一個開始時間,有兩種情況:
	//1:開始時間和第一個的程序到達時間一樣,即“來了就讓它執行”
	//2:如果第一程序的到達時間還沒到達設定的starttime,就讓它等會,等到starttime這個時間點了再讓它先執行
	//其他的排程不用設定開始時間,因為第一個來的先執行
	printf("\ninput the start time:");
	scanf("%d",&starttime);
	if(starttime>=pcb[1].arrivetime)
	{
		pcb[1].finishtime=pcb[1].servicetime+starttime;
	}
	else
	{
		pcb[1].finishtime=pcb[1].arrivetime+pcb[1].servicetime;
	}
    int i;
	//計算剩下程序的finishtime
	for(i=2;i<=n;i++)
	{
		if(pcb[i-1].finishtime>pcb[i].arrivetime)
			pcb[i].finishtime=pcb[i-1].finishtime+pcb[i].servicetime;
		else
			pcb[i].finishtime=pcb[i].arrivetime+pcb[i].servicetime;
    }
	//計算每一個程序的週轉時間和帶權週轉時間
    for(i=1;i<=n;i++)
        {
		pcb[i].turntime=pcb[i].finishtime-pcb[i].arrivetime;
		pcb[i].average_turntime=pcb[i].turntime/pcb[i].servicetime;
	}
}

void print_FCFS(int n)
{
	printf("process ID  arrivetime servicetime finishtime turntime  averageturntime  .\n");
    int i;
	//第一個程序從下標1開始
	for(i=1;i<=n;i++)
	{
		printf("%6d%11d%12d%12d%10d%12d",pcb[i].name  ,pcb[i].arrivetime  ,pcb[i].servicetime  ,pcb[i].finishtime  ,pcb[i].turntime  ,pcb[i].average_turntime);
		printf("\n");
	}

}
void time_segment(int n) //時間片輪轉,在時間片輪轉中只需要remain_time來表示一個程序需要的時間
{
	int i,j;
	int T;   //時間片長度
	int flag=1;   //就緒佇列中是否還有程序
	int time=0;
	int sum=0;   //已經完成的程序數

	//按各程序的arrivetime進行升序排列
	for(i=1;i<=n;i++)
	for(j=i+1;j<=n;j++)  
	{
		if(pcb[j].arrivetime<pcb[i].arrivetime)
		{
			pcb[0]=pcb[j];
			pcb[j]=pcb[i];
			pcb[i]=pcb[0];	
		}
	}
	time=pcb[1].arrivetime;//時間軸初始值
	printf("\ninput the slicetime:");
	scanf("%d",&T);
	while(sum<n) 
	{
		flag=0;   //當前就緒佇列中沒有程序
		int i;
        for(i=1;i<=n;i++)
		{
			if(pcb[i].sign==1) continue; //表示該程序已完成
			else
			{
	           //沒有完成的程序需要的時間大於一個時間片
				if(pcb[i].remain_time > T)
				{
					flag=1;
					time=time+T;
					pcb[i].remain_time=pcb[i].remain_time-T;

					
				}
				//沒有完成的程序需要的時間小於或等於一個時間片(在這種情況下才有finishtime)
				else if(pcb[i].remain_time <= T)
				{
					flag=1;  //加入就緒佇列
					time=time+pcb[i].remain_time;
					pcb[i].finishtime=time;

					pcb[i].turntime=pcb[i].finishtime - pcb[i].arrivetime;
					pcb[i].average_turntime = pcb[i].turntime/pcb[i].servicetime;

                    pcb[i].sign=1;//程序完成標誌sign,即退出就緒佇列
		 	        pcb[i].remain_time=0;//及時歸零
				}
				
				if(pcb[i].sign==1) sum++;
			}

		}//for


		if(flag==0&&sum<n)   // 還有沒執行的程序,且沒進入就就緒佇列 
		{
        	int i;
			for(i=1;i<=n;i++)
			if(pcb[i].sign==0) {time=pcb[i].arrivetime;break;}//如果有沒執行的程序,時間軸置放到它的到達時間上
		}


	}//while

}
void print_time(int n)
{   
	int i;
	for(i=1;i<=n;i++)
	{
		printf("\n processID runtime fihishtime turntime average_turntime\n");//程序名   服務時間   優先順序  完成時間
		printf("%6d%10d%10d%10d%10d",pcb[i].name,pcb[i].servicetime,pcb[i].finishtime,pcb[i].turntime,pcb[i].average_turntime);
		printf("\n");
	}
}

void Priority(int n)
{
	int i,j;
	int time = pcb[1].arrivetime;
	//按各程序的arrivetime進行升序排列,最早到達的程序先執行
	for(i=1;i<=n;i++)
	for(j=i+1;j<=n;j++)  
	{
		if(pcb[j].arrivetime < pcb[i].arrivetime)
		{
			pcb[0]=pcb[j];
			pcb[j]=pcb[i];
			pcb[i]=pcb[0];	
		}
	}
	printf("\n processID runtime priority fihishtime \n");//程序名   服務時間   優先順序  完成時間
	//先到達的程序第一個執行
	if(i=1)
	{
		pcb[i].finishtime=pcb[i].arrivetime + pcb[i].servicetime;
		time =pcb[i].arrivetime + pcb[i].servicetime;
		printf("%6d%10d%10d%10d",pcb[i].name,pcb[i].servicetime,pcb[i].priority,pcb[i].finishtime);
		printf("\n");
		i++;
	}

	//按各程序的priority進行降序排列,優先順序最高的程序先執行
	for(i=2;i<=n;i++)
	for(j=i+1;j<=n;j++)  
	{
		if(pcb[j].priority > pcb[i].priority)
		{
			pcb[0]=pcb[j];
			pcb[j]=pcb[i];
			pcb[i]=pcb[0];	
		}
	}
	
	for(i=2;i<=n;i++)
	{
		time = time + pcb[i].servicetime;
		pcb[i].finishtime = time;
		printf("%6d%10d%10d%10d",pcb[i].name,pcb[i].servicetime,pcb[i].priority,pcb[i].finishtime);
		printf("\n");
	}//for

}//void

void SJF(int n)//短作業優先並輸入程序個數
{
	int i,j;
	int time = pcb[1].arrivetime;//時間軸以第一個程序的到達時間為起點
	//按各程序的arrivetime進行升序排列,但最早到達的程序毋庸置疑先執行
	//只要有前後關係就有雙重for迴圈
	//目的求出第一個到達的程序在pcb[1]裡
	for(i=1;i<=n;i++)
	for(j=i+1;j<=n;j++)  
	{
		if(pcb[j].arrivetime < pcb[i].arrivetime)
		{
			pcb[0]=pcb[j];
			pcb[j]=pcb[i];
			pcb[i]=pcb[0];	
		}
	}

	printf("\n processID runtime fihishtime turntime average_turntime\n");//程序名   服務時間   優先順序  完成時間
	//先到達的程序第一個執行
	if(i=1)
	{
		pcb[i].finishtime=pcb[i].arrivetime + pcb[i].servicetime;
		time =pcb[i].arrivetime + pcb[i].servicetime;
		pcb[i].turntime=pcb[i].finishtime - pcb[i].arrivetime;
		pcb[i].average_turntime = pcb[i].turntime/pcb[i].servicetime;
		printf("%6d%10d%10d%10d%10d",pcb[i].name,pcb[i].servicetime,pcb[i].finishtime,pcb[i].turntime,pcb[i].average_turntime);
		printf("\n");
		i++;
	}
	//按各程序的服務時間進行升序排列,servicetime越短的程序先執行
	for(i=2;i<=n;i++)
	for(j=i+1;j<=n;j++)  
	{
		if(pcb[j].servicetime < pcb[i].servicetime)
		{
			pcb[0]=pcb[j];
			pcb[j]=pcb[i];
			pcb[i]=pcb[0];	
		}
	}
	//對排序後的程序序列進行計算
	for(i=2;i<=n;i++)
	{
		time = time + pcb[i].servicetime;
		pcb[i].finishtime = time;
		pcb[i].turntime=pcb[i].finishtime - pcb[i].arrivetime;
		pcb[i].average_turntime = pcb[i].turntime/pcb[i].servicetime;
		printf("%6d%10d%10d%10d%10d",pcb[i].name,pcb[i].servicetime,pcb[i].finishtime,pcb[i].turntime,pcb[i].average_turntime);
		printf("\n");
	}//for
}

				
void layout(int n)
{
	int i;
	for(i=0;;i++)
	{
		int ch=0;
		printf("\n");
		printf("\t\t************schedule algorithm************\n");
		printf("\t\t1.FSFS\n");
		printf("\t\t2.timesegment\n");
		printf("\t\t3.priority\n");
		printf("\t\t4.SJF\n");
		printf("\t\t5.Esc\n");
		printf("\t\tchoose the algorithm:");
		scanf("%10d",&ch);
		switch(ch)
		{
			case 1:
		    		FCFS(n);
		    		print_FCFS(n); break;
			case 2:
		    		time_segment(n);
		   			print_time(n); break;
			case 3:
		    		Priority(n); break;//print程式碼段已內建
			case 4:
					SJF(n);break;//print程式碼段已內建
			case 5:
					exit(0);
			default:printf("enter error data!\n");
			//P:int型別的變數,case後面不要加''
		}
	}
}

int main()
{ 
	int n;
	printf("Input the number of process: ");
	scanf("%d",&n);
	init(n);//初始化pcb陣列為零
	creat(n);//根據輸入資訊更改pcb陣列
	layout(n);
	return 0;
}

結果如下圖