程序流程
- 用户输入进程的数量,确定进程的开始时间,和进程的运行时间,优先数(越大优先权越高)。
- 选择调度规则。调度规则有:FCFS,SJF,RR,动态高优先权优先(需要特别设定优先权,并且可动态修改)。
- 最后输出进程的调度顺序和每个进程的运行时间,进程名_进程id(运行时间)。如:p1_1(2),p2_2(3),p3_3(4),p5_5(6)形式。
源码如下:
main.cpp
//进程调度模拟
#include<stdio.h>
#include<stdlib.h>
#define MAX_PROCESSES 10
#define MAX_NAME 5
int processes = 0;
#include"pcb_1.h"
pcb pcb_arrs[MAX_PROCESSES]={0};
#include"process_queue.h"
Queue ReadyQue;
#include"schedule_1.h"
//冒泡排序
void bubbleSortByArrive()
{
pcb tmp;
for(int i = 0; i < processes-1; i++){
for(int j = i+1; j < processes; j++){
if(pcb_arrs[i].pcb_beginning_time > pcb_arrs[j].pcb_beginning_time)
{
tmp = pcb_arrs[i];
pcb_arrs[i] = pcb_arrs[j];
pcb_arrs[j] = tmp;
}
}
}
}
// 欢迎界面
void welcome()
{
printf("#########################################################\n");
printf(" Welcome to Process scheduling simulation\n");
printf(" Author : @zsjjsd\n");
printf("#########################################################\n");
}
//输入进程的数量
void input_processes()
{
printf("Please input the number of processes(int,max=%d) : ",MAX_PROCESSES);
scanf("%d",&processes);
if(processes>MAX_PROCESSES)
{
printf("Processes too many!\n");
exit(0);
}
printf("processes : %d\n\n",processes);
}
//初始化进程
void initialize()
{
char name[MAX_NAME]={0};
int beignning_time = 0;
int running_time = 0;
for(int i = 0; i < processes; ++i)//创建对应数量的进程
{
printf("Please input the %d pcb_name(length = 5) : ",i+1);
scanf("%s",name);
printf("Please input the %d pcb_beginning_time(int) : ",i+1);
scanf("%d",&beignning_time);
printf("Please input the %d pcb_running_time(int) : ",i+1);
scanf("%d",&running_time);
pcb_arrs[i] = create_pcb(name,beignning_time,running_time);
}
}
//输出进程
void output_processes()
{
for(int j = 0; j < processes; ++j)
{
printf("pcb_id=%d,pcb_name=%s,pcb_beginning_time=%d,pcb_running_time=%d,pcb_privileges=%d\n",
pcb_arrs[j].pcb_id,pcb_arrs[j].pcb_name,pcb_arrs[j].pcb_beginning_time,pcb_arrs[j].pcb_running_time,pcb_arrs[j].pcb_privileges);
}
}
void chooseSchedule()
{
char flag = '0';
printf("Please choose the scheduling algorithm:\n");
printf(" Scheduling algorithm list:\n");
printf(" Press 1 for FCFS\n");
printf(" Press 2 for SJF\n");
printf(" Press 3 for RR\n");
printf(" Press 4 for PSA\n");
printf("Press your choose : ");
getchar();
flag = getchar();
if(flag=='1')
FCFS();
else if(flag=='2')
SJF();
else if(flag=='3')
RR();
else if(flag=='4')
PSA();
else
printf("Please press the correct char!\n");
}
int main(void)
{
/*
程序流程:
用户输入进程的数量,确定进程的开始时间,和进程的运行时间,优先数(越大优先权越高)。
选择调度规则。调度规则有:FCFS,SJF,RR,动态高优先权优先(需要特别设定优先权,并且可动态修改)。
最后输出进程的调度顺序和每个进程的运行时间,进程名_进程id(运行时间)。
如:p1_1(2),p2_2(3),p3_3(4),p5_5(6)形式。
*/
//---初始化进程
welcome();
input_processes();
initialize();
bubbleSortByArrive();//按到达时间排序
output_processes();
//-------------
printf("\n");
//执行进程调度
init(&ReadyQue);//初始化就绪队列
chooseSchedule();//选择调度算法
//-------------
destroyQue(&ReadyQue);
return 0;
}
pcb.h(进程控制块数据结构)
#ifndef _PCB_1_H
#define _PCB_1_H
#include<malloc.h>
#include<string.h>
int pcbId=0;
int pcb_ids[MAX_PROCESSES]={0};//存储pcb的所有id,保证每个pcb都是唯一的。创建pcb时加入id到此数组,删除pcb时,也从此删除
//进程控制块
typedef struct PCB{
int pcb_id;//pcb的id,每个pcb都是唯一的。
char pcb_name[MAX_NAME];//pcb的名字
int pcb_beginning_time;//进程的开始时间
int pcb_running_time;//进程的运行时间
int pcb_privileges;//进程的优先级,在需要优先级时初始化
}pcb,*ppcb;
//创建进程,即创建进程控制块,并初始化pcb
pcb create_pcb(char * name, int beginning_time, int running_time)
{
//初始化开始
pcb tPcb;
tPcb.pcb_id = pcbId+1;//初始化pcdid
pcb_ids[pcbId++] = tPcb.pcb_id;//记录创建的pcb
strcpy(tPcb.pcb_name,name);//初始化name
//tPcb.pcb_name = name;
tPcb.pcb_beginning_time = beginning_time;//初始化开始时间
tPcb.pcb_running_time = running_time;//初始化运行时间
tPcb.pcb_privileges = 0;//默认没有优先权。特定算法需要,可动态修改
//初始化完毕
printf("initialized over!pcb_id=%d,pcb_name=%s,pcb_beginning_time=%d,pcb_running_time=%d,pcb_privileges=%d\n\n",
tPcb.pcb_id,tPcb.pcb_name,tPcb.pcb_beginning_time,tPcb.pcb_running_time,tPcb.pcb_privileges);
return tPcb;
}
#endif
queue_1.h(队列数据结构)
#ifndef _PROCESS_QUEUE_H
#define _PROCESS_QUEUE_H
/*
2022年10月30日22点26分
完成队列的一些简单功能
循环队列关键的算法为:位置取补
(i+1)%length
*/
#define MAX_LENGTH (MAX_PROCESSES+1)
typedef pcb ElementType;
typedef struct Queue
{
ElementType *pBase;//数组首元素地址
int front;//队头
int rear;//队尾
}QUEUE, *pQUEUE;
void init(pQUEUE pQ)//初始化队列
{
pQ->pBase = (ElementType *)malloc(sizeof(ElementType) * MAX_LENGTH);
if(!pQ->pBase)
exit(-1);
pQ->front = 0;
pQ->rear = 0;
}
bool QueueFull(pQUEUE pQ)//判断队列是否为满
{
if(pQ->front == (pQ->rear+1) % MAX_LENGTH)
return true;
return false;
}
bool QueueEmpty(pQUEUE pQ)//判断队列是否为空
{
if(pQ->front == pQ->rear)
return true;
return false;
}
bool enQueue(pQUEUE pQ, ElementType val)//入队
{
if(QueueFull(pQ))
return false;
pQ->pBase[pQ->rear] = val;
pQ->rear = (pQ->rear+1) % MAX_LENGTH;
return true;
}
bool outQueue(pQUEUE pQ, ElementType * e)//出队
{
if(QueueEmpty(pQ))
return false;
*e = pQ->pBase[pQ->front];
pQ->front = (pQ->front+1) % MAX_LENGTH;
return true;
}
/*void traverse(pQUEUE pQ)//遍历队列
{
int i = pQ->front;
while(i != pQ->rear)
{
printf("%d ",pQ->pBase[i]);
i = (i+1) % MAX_LENGTH;
}
printf("\n");
}*/
int QueLength(pQUEUE pQ)//队列的长度
{
return (pQ->rear - pQ->front + MAX_LENGTH) % MAX_LENGTH;
}
void clearQue(pQUEUE pQ)//清空队列
{
pQ->front = pQ->rear = 0;
}
void destroyQue(pQUEUE pQ)//销毁队列
{
if(pQ->pBase)
free(pQ->pBase);
pQ->pBase = NULL;
pQ->front = pQ->rear = 0;
}
#endif
schedule.h(进程调度算法)
#ifndef _SCHEDULE_1_H
#define _SCHEDULE_1_H
//输出进程
void outputProcess(ppcb ptemp)
{
for(int j = 0; j < processes; ++j)
{
printf("pcb_id=%d,pcb_name=%s,pcb_beginning_time=%d,pcb_running_time=%d,pcb_privileges=%d\n",
ptemp[j].pcb_id,ptemp[j].pcb_name,ptemp[j].pcb_beginning_time,ptemp[j].pcb_running_time,ptemp[j].pcb_privileges);
}
}
void bubbleSortByRunning(ppcb pPcb,int cnt)
{
pcb tmp;
for(int i = 0; i < cnt-1; i++){
for(int j = i+1; j < cnt; j++){
if(pPcb[i].pcb_running_time > pPcb[j].pcb_running_time)
{
tmp = pPcb[i];
pPcb[i] = pPcb[j];
pPcb[j] = tmp;
}
}
}
}
void bubbleSortByPrivileges(ppcb pPcb,int cnt)
{
pcb tmp;
for(int i = 0; i < cnt-1; i++){
for(int j = i+1; j < cnt; j++){
if(pPcb[i].pcb_privileges < pPcb[j].pcb_privileges)
{
tmp = pPcb[i];
pPcb[i] = pPcb[j];
pPcb[j] = tmp;
}
}
}
}
//先来先服务
void FCFSService()
{
printf("FCFSService:\n\t");
int i = 0;
//将进程放入就绪队列中
while(true)
{
if(i == processes)
break;
printf("%s_%d(%d) ",pcb_arrs[i].pcb_name,pcb_arrs[i].pcb_id,pcb_arrs[i].pcb_running_time);//服务
i++;
}
printf("\n\n");
}
void SJForPSACPUService(ppcb arrive_arr,int cnt,int * now)
{
for(int i = 0; i < cnt; i++)
{
printf("%s_%d(%d) ",arrive_arr[i].pcb_name,arrive_arr[i].pcb_id,arrive_arr[i].pcb_running_time);
*now+=arrive_arr[i].pcb_running_time;
}
}
void getArrive(ppcb arrive_arr,int *i, int *cnt, int *now)
{
while(true)
{
if(*i == processes)
break;
if(pcb_arrs[*i].pcb_beginning_time <= *now)
{
arrive_arr[*cnt] = pcb_arrs[*i];
++*i;
++*cnt;
}
else
break;
}
}
void SJFService()
{
printf("SJFService:\n\t");
pcb arrive_arr[MAX_PROCESSES]={0};
int i = 0;
int cnt = 0;
int now = pcb_arrs[0].pcb_beginning_time;
//将进程按SJF算法排序放入就绪队列中。
//取出已到达的进程,按运行时间从小到大排序,放入就绪队列中。并且进行服务,
while(true)
{
cnt = 0;
if(i == processes)
break;
//取出已到达的进程,根据时间找。
getArrive(arrive_arr,&i,&cnt,&now);
bubbleSortByRunning(arrive_arr,cnt);
SJForPSACPUService(arrive_arr,cnt,&now);
}
printf("\n");
}
void RRCPUService(int *now, int *that, ppcb tmp_arr, int serviceTime)
{
int i = 0;
pcb tmp;
outQueue(&ReadyQue,&tmp);
serviceTime = tmp.pcb_running_time > serviceTime ? serviceTime : tmp.pcb_running_time;
printf("%s_%d(%d) ",tmp.pcb_name,tmp.pcb_id,serviceTime);
*now += serviceTime;
tmp.pcb_running_time -= serviceTime;
//在服务的进程插入队尾之前,已到达的进程要先插入。
for(i = *that; i < processes; i++)
{
if(tmp_arr[i].pcb_beginning_time <= *now)
enQueue(&ReadyQue,tmp_arr[i]);
else
break;
}
*that = i;
if(tmp.pcb_running_time > 0)
enQueue(&ReadyQue,tmp);
}
void RRService(int slot)
{
printf("RRService:\n\t");
int now = 0;
pcb tmp_arr[MAX_PROCESSES] = {0};
for(int i = 0; i < processes; i++)
{
tmp_arr[i] = pcb_arrs[i];
}
enQueue(&ReadyQue,pcb_arrs[0]);
int that = 1;
while(!QueueEmpty(&ReadyQue))
RRCPUService(&now,&that,tmp_arr,slot);
printf("\n");
}
void setPrivileges(ppcb temp,int cnt)
{
for(int i = 0; i < cnt; i++)
{
printf("\tPlease input %s_%d privileges : ",temp[i].pcb_name,temp[i].pcb_id);
scanf("%d",&temp[i].pcb_privileges);
}
}
void PSAService()
{
printf("PSAService:\n");
int i = 0;
int cnt = 0;
int now = 0;
pcb temp[MAX_PROCESSES] = {0};
while(true)
{
cnt = 0;
if(i == processes)
break;
getArrive(temp,&i,&cnt,&now);
setPrivileges(temp,cnt);
bubbleSortByPrivileges(temp,cnt);
printf("\t\t");
SJForPSACPUService(temp,cnt,&now);
printf("\n");
}
}
/*
先来先服务算法,先将进程按到达时间放入队列中,可以先将进程按到达时间排序,然后由小到大放入队列中。
再从队列中取出进程进行服务。,最后输出服务进程和时间。
*/
void FCFS()
{
printf("FCFS\n");
//开始服务并输出服务信息
FCFSService();
}
void SJF()
{
printf("SJF\n");
SJFService();
}
void RR()
{
int slot = 2;//时间片
printf("RR\n");
RRService(slot);
}
void PSA()
{
printf("PSA\n");
PSAService();
}
#endif