操作系统 单处理器进程调度模拟实验(c++)

2019-07-14 10:35发布

本实验模拟了时间片轮转调度算法下的单处理机进程调度。 数据结构以进程控制块PCB为基本单位。 逻辑结构简单描述为,存在一个准备就绪的队列,用来组织PCB。 程序开始,需要输入运行时间片长度,再录入程序。程序需要数字编号和执行长度。 位于队列头的PCB出队,变为执行态,执行(与模拟的系统寄存器空间交互),执行完毕后,改为就绪态,再次加入队尾。
#include
#include
#include
#include
#include

//进程控制块数据类型
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("
异常!");
}
//将队头元素出队
QueuePtr DeQueue(ReadyQueue *q){
	if(q->front==q->rear){
		printf("
全部执行完毕队列为空!");
		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("
系统已销毁!");
}

//创建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("


");
	printf("当前运行的程序为:
");
	printf("	进程号: %d
",osRegister.ID);
	printf("	进程工作量: %d
",osRegister.COUNT);
	printf("	进程状态: ");putchar(osRegister.STATUES);
	printf("

");
	printf("	寄存器信息
AX	BX	CX	DX	PC	PSW
");
	printf("%d	%d	%d	%d	%d	%d
",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("进程调度程序开始执行! ^-^

");
	printf("请输入时间片长度(秒):
");
	scanf("%d",&time);
	printf("(注意:请输入进程号(非负整数)和该进程的工作量(整数),输入完最后一个进程后,回车并输入两个负整数结束:)

");
	for(int i=1;i<11;i++)
	{	
		fflush(stdin);
		printf("请输入第%d个进程的 进程号和工作量:
",i);
		scanf("%d%d",&Id,&Count);
		if(Id<0)
			break;
		pcb = (QueuePtr)Create(Id,Count);
		EnQueue(q,pcb);
		
	}
	schedule();
	system("pause");
}