1. 程式人生 > >作業系統 單處理器程序排程模擬實驗(c++)

作業系統 單處理器程序排程模擬實驗(c++)

本實驗模擬了時間片輪轉排程演算法下的單處理機程序排程。

資料結構以程序控制塊PCB為基本單位。

邏輯結構簡單描述為,存在一個準備就緒的佇列,用來組織PCB。

程式開始,需要輸入執行時間片長度,再錄入程式。程式需要數字編號和執行長度。

位於佇列頭的PCB出隊,變為執行態,執行(與模擬的系統暫存器空間互動),執行完畢後,改為就緒態,再次加入隊尾。

</pre><pre name="code" class="cpp">#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>
#include<Windows.h>
#include<conio.h>

//程序控制塊資料型別
typedef struct pcb
{
	int id;					//程序號
	int count;  			//程序工作量
	char status;  			//程序狀態(R和W和F)
	int ax, bx, cx,dx; 	//程序現場資訊,通用暫存器內容
	int pc;         		//程序現場資訊,程式計數器內容
	int psw;       		//程序現場資訊,程式狀態字暫存器內容
	struct pcb *next;       		//下一個程序控制塊的位置
} PCB,*QueuePtr;

//就緒佇列的指標
typedef struct 
{
	QueuePtr front;
	QueuePtr rear;
} ReadyQueue;

//系統暫存器資料型別
typedef struct
{	
	int ID;
	int COUNT;
	char STATUES;
	int AX,BX,CX,DX,PC,PSW;
} OsRegister;

//公用變數
ReadyQueue *q;
QueuePtr pcb;
OsRegister osRegister;
int time;
//就緒佇列操作方法

//判斷佇列是否為空
int IsEmpty(ReadyQueue *q){
	if(q->front==q->rear)
		return 1;
	else
		return 0;
}

//初始化就緒佇列
ReadyQueue *InitQueue(){
	ReadyQueue *q = (ReadyQueue *)malloc(sizeof(ReadyQueue));
	if(q!=NULL){
		q->front = q->rear = (QueuePtr)malloc(sizeof(PCB));
		q->front->next = NULL;
	}
	else
		exit(1);
	return q;
}

//將新元素插入隊尾
void EnQueue(ReadyQueue *q,QueuePtr pcb){
	if(&pcb!= NULL){
			q->rear->next = pcb;
			q->rear = pcb;
	}else
		printf("\n異常!");
}
//將隊頭元素出隊
QueuePtr DeQueue(ReadyQueue *q){
	if(q->front==q->rear){
		printf("\n全部執行完畢佇列為空!");
		system("pause");
		exit(0);
	}
	QueuePtr pcb;
	pcb = q->front->next;
	q->front->next = pcb->next;
	if(q->rear==pcb)
		q->rear = q->front;
	return pcb;
}

//清空佇列
void ClearQueue(ReadyQueue *q){
	while(IsEmpty(q)!=1)
		DeQueue(q);
}
//銷燬就緒佇列
void DestroyQueue(ReadyQueue *q){
	if(IsEmpty(q)!=1)
		ClearQueue(q);
	free(q);
	printf("\n系統已銷燬!");
}

//建立PCB
QueuePtr Create(int id,int count){
	//申請新PCB
	QueuePtr pcb = (QueuePtr)malloc(sizeof(PCB));
	//初始化PCB
	pcb->id = id;
	pcb->count = count;
	pcb->ax = 0;
	pcb->bx = 0;
	pcb->cx = 0;
	pcb->dx = 0;
	pcb->pc = 0;
	pcb->psw = 0;
	pcb->status = 'W';
	//返回PCB的指標
	return pcb;
}
//程序排程函式
void schedule(){
	while(1){
	//出佇列
	pcb = DeQueue(q); 
	//加入系統處理器中,改為執行態
	osRegister.STATUES = pcb->status = 'R';
	osRegister.ID = pcb->id;
	osRegister.COUNT = pcb->count;
	//用自增來模擬執行過程,並伴隨暫存器的改變
	osRegister.AX = ++pcb->ax;
	osRegister.BX = ++pcb->bx;
	osRegister.CX = ++pcb->cx;
	osRegister.DX = ++pcb->dx;
	osRegister.PC = ++pcb->pc;
	osRegister.PSW = ++pcb->psw;
	printf("\n\n\n");
	printf("當前執行的程式為:\n");
	printf("	程序號: %d\n",osRegister.ID);
	printf("	程序工作量: %d\n",osRegister.COUNT);
	printf("	程序狀態: ");putchar(osRegister.STATUES);
	printf("\n\n");
	printf("	暫存器資訊\nAX\tBX\tCX\tDX\tPC\tPSW\n");
	printf("%d\t%d\t%d\t%d\t%d\t%d\n",osRegister.AX,osRegister.BX,osRegister.CX,osRegister.DX,osRegister.PC,osRegister.PSW);
	if(osRegister.PSW == osRegister.COUNT){
		osRegister.STATUES = pcb->status = 'F';
		printf("--------該程序執行完畢!--------        ");
		continue;
	}
	//用一段時間的休眠來模擬時間片下的計算
	Sleep(time*1000);
	pcb->status = 'W';
	//將執行完時間片的程序加入佇列尾
	EnQueue(q,pcb);

	}
}

//主函式
void main(){
	//輸入控制
	int Id;
	int Count;
	q = InitQueue();
	printf("程序排程程式開始執行! ^-^\n\n");
	printf("請輸入時間片長度(秒):\n");
	scanf("%d",&time);
	printf("(注意:請輸入程序號(非負整數)和該程序的工作量(整數),輸入完最後一個程序後,回車並輸入兩個負整數結束:)\n\n");
	for(int i=1;i<11;i++)
	{	
		fflush(stdin);
		printf("請輸入第%d個程序的 程序號和工作量:\n",i);
		scanf("%d%d",&Id,&Count);
		if(Id<0)
			break;
		pcb = (QueuePtr)Create(Id,Count);
		EnQueue(q,pcb);
		
	}
	schedule();
	system("pause");
}