1. 程式人生 > >C語言實現作業系統程序排程演算法

C語言實現作業系統程序排程演算法

模擬實現作業系統程序排程

本程式介紹對於非搶佔式多道批處理系統的程序排程演算法
本程式在完成排程演算法的基礎上動態模擬實現了程序隨時刻達到和結束的整個過程。

先來先服務原理分析:
每個程序都有自身的達到時間,在作業系統中,首先處理先到的程序,後到的程序需要等待先到達的程序執行完畢才能被執行。本程式在設計當中對於到到達時間相同的程序使用的處理辦法是優先服務時間短較短的程序。

短程序優先原理分析:
首先在一開始就需要找到當前達到程序當中服務時間最短的程序,用於執行,在該程序執行當中,可能會有其他程序達到,這個過程中,不搶佔當前正在執行的程序。等待該程序結束以後,又開始從所有當前時刻已到達(包括之前的就緒程序,不包括已執行)的程序當中尋找程序服務時間最短的程序用於執行,依照此法,直到所有程序執行完畢。本程式在設計當中對於當前時刻到達的所有程序,存在服務時間相同的情況處理為先到的程序先執行。

程序控制塊(PCB)的定義:

struct PCB
{
	char name;	
	float arrivetime;	//達到時間
	float servetime;	//執行(服務)時間
	float finishtime;	//結束(完成)時間
	float roundtime;	//週轉時間
	float daiquantime;	//帶權週轉時間
};
struct PCB a[100];		//結構體陣列

主要變數說明:

int time = 0;	    	//定義當前時刻
int jcnum = 0;	    	//定義當前程序指向
struct PCB t;	    	//定義一個空的結構體節點
int jcztsy = 0;	    	//定義程序狀態索引
bool ztgb = false;		//在短程序當中是否有存在目標程序

函式說明:

void tjxx(int n)		    //列印統計資訊
void xlxfw(int n) 		    //先來先服務
void djcyx(int n) 	  	    //短程序優先
int xxlr()				    //資訊錄入
void main()		            //主函式

完整程式碼:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <windows.h> 
//程序控制塊(PCB)
struct PCB
{
	char name;
	float arrivetime;
	float servetime;
	float finishtime;
	float roundtime;
	float daiquantime;
};

struct PCB a[100];
struct PCB b[100];
char *jczt[] = { "執行", "就緒" };//*表示沒有字串的大小限制

//列印統計資訊
void tjxx(int n)
{
	float averoundtime = 0.0f;		//定義平均週轉時間
	float avedaiquantime = 0.0f;	//定義平均帶權週轉時間
	printf("按任意鍵檢視統計資訊");
	getchar(); getchar();
	printf("\n\n程序名稱\t到達時間\t服務時間\t完成時間\t週轉時間\t帶權週轉時間");
	for (int j = 0; j < n; j++)
	{
		printf("\n   %c\t\t%4.f\t\t%4.f\t\t%4.f\t\t%4.f\t\t  %.2f\n", a[j].name, a[j].arrivetime, a[j].servetime, a[j].finishtime, a[j].roundtime, a[j].daiquantime);
		averoundtime += a[j].roundtime;
		avedaiquantime += a[j].daiquantime;
	}

	printf("\n平均週轉時間:%.2f", averoundtime / n);
	printf("\n\n平均帶權週轉時間:%.2f\n", avedaiquantime / n);
}
//先來先服務
void xlxfw(int n)
{
	int time = 0;				//定義當前時刻
	int jcnum = 0;				//定義當前程序指向
	struct PCB t;				//定義一個空的結構體節點
	int jcztsy = 0;				//定義程序狀態索引
	while (1)
	{
		printf("當前時刻:%2d\n", time);
		//排序
		for (int i = 1; i < n; i++)
		{
			for (int j = 0; j < n - i; j++)
			{
				if (a[j].arrivetime > a[j + 1].arrivetime)
				{
					t = a[j];
					a[j] = a[j + 1];
					a[j + 1] = t;
				}
				if (a[j].arrivetime == a[j + 1].arrivetime)
				{
					if (a[j].servetime > a[j + 1].servetime)
					{
						t = a[j];
						a[j] = a[j + 1];
						a[j + 1] = t;
					}
				}
			}
		}
		//遍歷陣列,注意同時達到的程序,所以採用for迴圈遍歷
		for (int k = 0; k< n; k++)
		{
			//是否有程序的到達時間等於當前時刻
			if (time == a[k].arrivetime && a[k].arrivetime != 0)
			{
				//判斷到達程序因該處於什麼狀態
				if (k >= 1 && time >= a[k - 1].finishtime || k == 0)
				{
					jcztsy = 0;
				}
				else
				{
					jcztsy = 1;
				}
				printf("\t\t-------------------------------------------------------------------\n");
				printf("\t\t程序 %c 到達\t程序狀態\n", a[k].name);
				printf("\n\t\t\t\t  %s\n", jczt[jcztsy]);
				printf("\t\t-------------------------------------------------------------------\n\n");

				//必須這樣寫,0在下,1在上
				if (jcnum >= 1)
				{
					a[k].finishtime = a[k - 1].finishtime + a[k].servetime;
					a[k].roundtime = a[k].finishtime - a[k].arrivetime;
					a[k].daiquantime = a[k].roundtime / a[k].servetime;
				}
				if (jcnum == 0)
				{
					a[k].finishtime = a[k].arrivetime + a[k].servetime;
					a[k].roundtime = a[k].finishtime - a[k].arrivetime;
					a[k].daiquantime = a[k].roundtime / a[k].servetime;

					printf("\t\t-----------------------------\n");
					printf("\t\t\t程序  %c  開始\n", a[jcnum].name);
					printf("\t\t-----------------------------\n\n");
					jcnum++;
				}
			}
			//是否有程序的結束時間等於當前時刻
			if (time == a[k].finishtime && a[k].finishtime != 0)
			{
				printf("\t\t-----------------------------\n");
				printf("\t\t\t程序  %c  完成\n", a[k].name);
				printf("\t\t-----------------------------\n\n");
			}
			//當前時刻是否滿足大於等於下一程序達到時間,同時大於等於前一程序結束時間
			if ((k >= 1 && time >= a[k].arrivetime && time == a[k - 1].finishtime && a[k].arrivetime != 0))
			{
				printf("\t\t-----------------------------\n");
				printf("\t\t\t程序  %c  開始\n", a[k].name);
				printf("\t\t-----------------------------\n\n");
			}
		}
		//判斷最後一個程序的結束沒有,結束跳出迴圈
		if (time > a[n - 1].finishtime && a[n - 1].finishtime != 0)
		{
			printf("\t\t-------------------------------------\n");
			printf("\t\t\t現有程序已載入完畢! ^_^\n");
			printf("\t\t-------------------------------------\n\n");
			break;
		}
		time++;
		Sleep(1000);
	}
	tjxx(n);
}
//短程序優先
void djcyx(int n)
{
	struct PCB t;
	int time = 0;//定義當前時刻
	int jcnum = 0;
	int jcztsy = 0;
	bool ztgb = false;

	//排序
	for (int i = 1; i < n; i++)
	{
		for (int j = 0; j < n - i; j++)
		{
			if (a[j].arrivetime > a[j + 1].arrivetime)
			{
				t = a[j];
				a[j] = a[j + 1];
				a[j + 1] = t;
			}
		}
	}

	while (1)
	{
		printf("當前時刻:%d\n", time);
		//遍歷陣列,注意同時達到的程序,所以採用for迴圈遍歷
		for (int k = 0; k< n; k++)
		{
			//是否有程序的到達時間等於當前時刻
			if (time == a[k].arrivetime && a[k].arrivetime != 0)
			{
				//判斷到達程序因該處於什麼狀態
				if (k >= 1 && time >= a[k - 1].finishtime || k == 0)
				{
					jcztsy = 0;
				}
				else
				{
					jcztsy = 1;
				}

				printf("\t\t-------------------------------------------------------------------\n");
				printf("\t\t程序 %c 到達\t程序狀態\n", a[k].name);
				printf("\n\t\t\t\t  ----\n");
				printf("\t\t-------------------------------------------------------------------\n\n");
			}
		}

		if (jcnum == 0)
		{
			//遍歷陣列
			for (int i = jcnum; i < n; i++)
			{
				//把當前到達的程序篩選出來
				if (time >= a[i].arrivetime)
				{
					//從挑選出來的程序中選取服務時間最短的一個
					if (a[i].servetime < a[jcnum].servetime)
					{
						t = a[jcnum];
						a[jcnum] = a[i];
						a[i] = t;
					}
					ztgb = true;
				}
			}
			if (ztgb == true)
			{
				printf("\t\t-----------------------------\n");
				printf("\t\t\t程序  %c  開始\n", a[jcnum].name);
				printf("\t\t-----------------------------\n\n");
				a[jcnum].finishtime = a[jcnum].arrivetime + a[jcnum].servetime;
				a[jcnum].roundtime = a[jcnum].finishtime - a[jcnum].arrivetime;
				a[jcnum].daiquantime = a[jcnum].roundtime / a[jcnum].servetime;
				ztgb = false;
				jcnum++;
			}
		}
		if (time == a[jcnum - 1].finishtime && a[jcnum - 1].finishtime != 0)
		{
			printf("\t\t-----------------------------\n");
			printf("\t\t\t程序  %c  完成\n", a[jcnum - 1].name);
			printf("\t\t-----------------------------\n\n");

			//遍歷陣列
			for (int i = jcnum; i < n; i++)
			{
				//把當前到達的程序篩選出來
				if (time >= a[i].arrivetime)
				{
					//從挑選出來的程序中選取服務時間最短的一個
					if (a[i].servetime < a[jcnum].servetime)
					{
						t = a[jcnum];
						a[jcnum] = a[i];
						a[i] = t;
					}
					ztgb = true;
				}
			}
			if (ztgb == true || jcnum == n - 1)
			{
				printf("\t\t-----------------------------\n");
				printf("\t\t\t程序  %c  開始\n", a[jcnum].name);
				printf("\t\t-----------------------------\n\n");
				a[jcnum].finishtime = a[jcnum - 1].finishtime + a[jcnum].servetime;
				a[jcnum].roundtime = a[jcnum].finishtime - a[jcnum].arrivetime;
				a[jcnum].daiquantime = a[jcnum].roundtime / a[jcnum].servetime;
				ztgb = false;
				jcnum++;
			}
		}
		if (time > a[n - 1].finishtime && a[n - 1].finishtime != 0)
		{
			printf("\t\t-------------------------------------\n");
			printf("\t\t\t現有程序已載入完畢! ^_^\n");
			printf("\t\t-------------------------------------\n\n");
			break;
		}
		time++;
		Sleep(1000);
	}
	tjxx(n);
}
//資訊錄入
int xxlr()
{
	int n = 0;
	srand(time(NULL)); //初始化隨機函式     	
	printf("\n\t\t請輸入需要的程序數:");
	scanf_s("%d", &n);
	printf("\n");
	for (int i = 0; i < n; i++)
	{
		printf("\t\t程序 %d\t名稱:", i + 1);
		scanf_s("%s", &a[i].name);
		a[i].arrivetime = (float)(rand() % 5 + 1);
		a[i].servetime = (float)(rand() % 5 + 1);
	}
	system("cls");
	return n;
}

void main()
{
	int b = 1, k;
	while (b)
	{
		system("cls");
		printf("\n\n\t\t程序排程演算法\n\n");
		printf("\t\t ----------------------------\n");
		printf("\t\t|1.... 先來先服務演算法        |\n");
		printf("\t\t|2.... 短程序優先演算法        |\n");
		printf("\t\t|3.... 退出程式              |\n");
		printf("\t\t ----------------------------\n");
		printf("\t\t請選擇:");
		scanf_s("%d", &k);
		switch (k)
		{
		case 1:	 xlxfw(xxlr());    	break;
		case 2:  djcyx(xxlr());     break;
		case 3:  b = 0;               break;
		default:printf("\n\t\t請輸入正確的選擇!\n");
		}
		if (b != 0)
		{
			printf("\n"); system("pause");
		}
	}
	printf("\n\t\t謝謝使用!\n\n\t\t");
}

如有錯誤,歡迎指正! _