本实验模拟了时间片轮转调度算法下的单处理机进程调度。
数据结构以进程控制块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");
}