作業系統:程式狀態轉換模擬,C語言實現

政威發表於2020-10-02

編寫並除錯一個模擬的程式排程和程式狀態轉換過程,採用“基於時間片輪轉法”排程演算法對N(N不小於5)個程式進行排程。要求使用C/C++程式設計實現(如有難度也可酌情使用Java或C#實現)。首先繪製流程圖,然後將程式原始碼和執行效果放入實驗報告中。
簡單輪轉法的基本思想是:所有就緒程式按先來先服務的方式排成一個佇列,總是把處理機分配給隊頭的程式,各程式佔用CPU的時間片長度相同(如1個CPU時間單位)。當把處理機分配給隊頭的程式後,該程式出就緒佇列,並將程式狀態從就緒態變化為執行態。如果執行程式用完它的時間片後還未完成,就把它送回到就緒佇列的末尾,同時將程式狀態從執行態變換為就緒態,把處理機重新分配給就緒隊頭的程式。當程式所需的CPU時間全部被滿足後,將該程式加入已完成執行程式佇列,並記錄其完成時間(第幾個CPU時間片單位時完成)。直至所有的程式執行完畢。
程式原始碼中必須顯著註釋標明PCB的資料結構(用於記錄模擬的程式的狀態、完成時間和連結資訊等)。需要在程式執行時列印輸出版權資訊:如姓名、班級、學號。
隨機生成N>3個程式(也可以手動順序錄入程式個數和每個程式,按生成/錄入順序組成就緒佇列),並生成/錄入每個程式的時間片需求,模擬各個程式執行過程。比如錄入3個程式分別為P1、P2、P3,需求的CPU時間分別為5、3、4個時間片單位,那麼程式模擬該3個程式的執行及狀態轉換過程,輸出為:
T1時刻:P1使用了1個CPU時間片,P1需求剩餘時間片為4,就緒佇列為P2(3個時間片)->P3(4個時間片),執行完成的程式為:空。
T2時刻:P2使用了1個CPU時間片,P2需求剩餘時間片為2,就緒佇列為P3(4個時間片)->P1(4個時間片),執行完成的程式為:空。
T3時刻:P3使用了1個CPU時間片,P3需求剩餘時間片為3,就緒佇列為P1(4個時間片)->P2(2個時間片),執行完成的程式為:空。
T4時刻:P1使用了1個CPU時間片,P1需求剩餘時間片為3,就緒佇列為P2(2個時間片)->P3(3個時間片),執行完成的程式為:空。

C程式碼如下(VS2019):

#include<stdio.h>
#include<stdlib.h>
struct ProcessOfMy
{//定義程式
	int name;
	int timeRequire;
	//1為就緒態,0為執行態,-1為已經完成
	int currentState;
	ProcessOfMy* next;
};
typedef struct ProcessOfMy PCB;
struct PCBQueue
{//定義PCB佇列
	int numOfProcess=0;
	ProcessOfMy *front, *rear;
	
};
typedef struct PCBQueue PCBQueue;

PCB* InitPCBQuee(PCB* process)
{
	PCB*queue = (PCB*)malloc(sizeof(PCB));
	if (queue == NULL)
	{
		return NULL;
	}
	queue->next=NULL;
	process = queue;
	return process;
}

PCB* EnProcess(PCB*rear,int a)
{//加入佇列
	PCB* p = (PCB*)malloc(sizeof(PCB));
	if (p == NULL)
	{
		return NULL;
	}
	int timeRequire = rand()%15;
	p->currentState = 1;
	p->timeRequire = timeRequire;
	p->name = a;
	p->next = NULL;
	rear->next = p;
	rear = p;
	return rear;
}

PCB* DeProcess(PCB* front, PCB* rear)
{//從佇列中刪除
	PCB* p;
	p = front;
	front = front->next;
	p->next = NULL;
	rear->next = front;
	
	return front;
}

PCB* SchProcess(PCB*front, PCB*rear)
{//將完成一個時間片的程式加入隊尾
	rear->next = front;
	return rear;
}

void ChangeCurrentState(PCBQueue  *PCB)
{//若隊頭程式完成,改變該程式的狀態
	PCB->front->currentState = -1;

}

void PrintReadyProcess(PCBQueue *pcbQueue)
{//列印出就緒佇列中的程式
	printf("就緒佇列有%d個程式:\n", pcbQueue->numOfProcess);
	PCB* p;
	int i;
	
	for (p = pcbQueue->front,i=0;i!=pcbQueue->numOfProcess;i++,p = p->next)
	{
		printf("程式%d(剩餘%d單位時間片)\n", p->name, p->timeRequire);
		
	}
	printf("\n");
}



int main()
{
	printf("2018015276 軟體18-2 張政威");
	PCB   process, * front, * rear,*cpFront,*cpRear,cpProcess,*p,*p1;
	//建立PCB
	PCBQueue pcbQueue;
	//初始化就緒佇列
	front = rear = InitPCBQuee(&process);
	//初始化已完成佇列
	cpFront=cpRear= InitPCBQuee(&cpProcess);
	int i;
	for (i = 0;i < 5;i++)
	{//初始化程式
		rear = EnProcess(rear, i);
		if (i == 0)
		{
			front = rear;
		}
		pcbQueue.rear = rear;
		pcbQueue.numOfProcess++;
		printf("程式%d 時間片要求%d\n", rear->name, rear->timeRequire);

	}
	//隊尾指向隊頭形成迴圈佇列
	rear->next = front;

	pcbQueue.front = front;
	pcbQueue.rear = rear;
	

	printf("\n");

	while (pcbQueue.numOfProcess!=0)
	{
		//對第一個程式操作並且操作完之後判斷
		pcbQueue.front->timeRequire--;
		printf("程式%d使用了一個CPU時間片,還需要%d個時間片\n", pcbQueue.front->name, pcbQueue.front->timeRequire);

		if (pcbQueue.front->timeRequire == 0)
		{//判斷第一個程式是否完成,若完成則釋放並且程式數減一
			printf("程式%d完成,出隊\n", pcbQueue.front->name);
			ChangeCurrentState(&pcbQueue);
			p = pcbQueue.front;
			//從佇列中刪除隊頭已完成的程式
			pcbQueue.front=DeProcess(pcbQueue.front, pcbQueue.rear);
			p->next = NULL;
			//將刪除的程式加入已完成佇列,並且輸出整個已完成佇列的名單
			cpRear->next = p;
			cpRear = p;
			printf("已完成的程式有:");
			for (p1 = cpFront->next;p1 != NULL;p1 = p1->next)
			{
				printf("%d ", p1->name);
			}
			printf("\n");
			//PCB中就緒程式數減一
			pcbQueue.numOfProcess--;
			PrintReadyProcess(&pcbQueue);
			continue;
		}
		//隊頭,隊尾前進
		pcbQueue.rear = pcbQueue.rear->next;
		pcbQueue.front = pcbQueue.front->next;
		PrintReadyProcess(&pcbQueue);

	}
	printf("作者資訊C語言實現\n");
	return 1;
	
}

相關文章