#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define TAKEIN "Takein"//吸纳状态
#define WAIT "Wait"//就绪状态
#define RUN "Run"//运行状态
#define FINISH "Finish"//完成状态
#define JOBNUMBER 5 //设置进程测试数为5
#define MIN 100
#pragma warning(disable:4996)
typedef struct PCB {
char jobName[10];//作业号
int arriveTime;//到达时间
int runTime;//需要运行时间
int startTime;//开始时间
int endTime;//完成时间
int turnoverTime;//周转时间
int run_flag; //调度标志
int start_flag; //是否为第一次开始调度
float useWeightTurnoverTime;//带权周转时间
char processStatus[10];//进程状态
}PCB;
static int currentTime = 0;
static int finishNumber = 0;
char JobArray[JOBNUMBER][10];
static int indexJob = 1;
PCB pcb[10]; //进程
PCB copy_pcb[10]; //备份进程
//创建PCB
void createPCB(struct PCB* pcb) {
printf("请输入5个进程名,系统将随机生成5个进程及数据:");
for (int i = 0; i < 5; i++) {
scanf("%s", &pcb[i].jobName);//作业号
}
printf("作业号 到达时间 需要运行时间\n");
for (int i = 0; i < 5; i++) {
pcb[i].arriveTime = rand() % 10;
pcb[i].runTime = rand() % 9 + 1;
pcb[i].startTime = 0;
pcb[i].endTime = 0;
pcb[i].turnoverTime = 0;
pcb[i].useWeightTurnoverTime = 0.0;
strcpy(pcb[i].processStatus, TAKEIN);
pcb[i].start_flag = 0;
printf("%s\t%d\t%d\n", pcb[i].jobName, pcb[i].arriveTime, pcb[i].runTime);
}
printf("---------------------------------------------\n");
struct PCB copy_pcb[10];//备份
for (int j = 0; j < 5; j++)
{
copy_pcb[j] = pcb[j];//对进程的初始化信息备份
}
getchar();
}
//打印用途
void printJob(struct PCB* pcb) {
printf("当前时间为%d\n", currentTime);
printf("作业号 到达时间 需要运行时间 开始时间 完成时间 周转时间 带权周转时间 进程状态\n");
for (int i = 0; i < JOBNUMBER; i++) {
if (strcmp(pcb[i].processStatus, FINISH) == 0)//如果进程为finish状态,这样输出
printf("%s\t%d\t%4d\t\t%d\t%d\t %d\t%.2f\t%s\n", pcb[i].jobName, copy_pcb[i].arriveTime, copy_pcb[i].runTime, pcb[i].startTime, pcb[i].endTime, pcb[i].turnoverTime, pcb[i].useWeightTurnoverTime, pcb[i].processStatus);
else if (strcmp(pcb[i].processStatus, RUN) == 0)//如果进程为run状态,这样输出
printf("%s\t%d\t%4d\t\t%d\t运行中\t none\tnone \t%s\n", pcb[i].jobName, copy_pcb[i].arriveTime, copy_pcb[i].runTime, pcb[i].startTime, pcb[i].processStatus);
else if (strcmp(pcb[i].processStatus, WAIT) == 0)//如果进程为wait状态,这样输出
printf("%s\t%d\t%4d\t\t等待\tnone\t none\tnone \t%s\n", pcb[i].jobName, copy_pcb[i].arriveTime, copy_pcb[i].runTime, pcb[i].processStatus);
else //如果进程为take in状态,这样输出
printf("%s\t%d\t%4d\t\t未运行\tnone\t none\tnone \t%s\n", pcb[i].jobName, copy_pcb[i].arriveTime, copy_pcb[i].runTime, pcb[i].processStatus);
}
printf("---------------------------------------------\n");
}
//根据当前时间修改status状态
void statusConfirm(struct PCB* pcb) {
for (int i = 0; i < JOBNUMBER; i++) {
//将当前时间为进程的到达时间,修改take in状态改为Wait状态
if (currentTime >= pcb[i].arriveTime && strcmp(pcb[i].processStatus, TAKEIN) == 0) {
strcpy(pcb[i].processStatus, WAIT);
}
}
}
//确定当前时间wait进程中最短进程的数组下标,没有wait进程则返回-1
int shortIndex(struct PCB* pcb) {
int min = MIN, temp = -1;
statusConfirm(pcb);
for (int i = 0; i < JOBNUMBER; i++) {
if (strcmp(pcb[i].processStatus, WAIT) == 0) {
if (pcb[i].runTime <= min) {
min = pcb[i].runTime;
temp = i;
}
}
}
return temp;
}
//确定当前时间wait进程中到达时间最小并且上一轮未执行的进程的数组下标,没有wait进程则返回-1
int fastIndex(struct PCB* pcb) {
int min = MIN, temp = -1;
statusConfirm(pcb);
for (int i = 0; i < JOBNUMBER; i++) {
if (strcmp(pcb[i].processStatus, WAIT) == 0) {
if (pcb[i].arriveTime <= min) {
min = pcb[i].arriveTime;
temp = i;
}
}
}
return temp;
}
//确定当前时间wait进程中响应比最高进程的数组下标,没有wait进程则返回-1
int PrioIndex(struct PCB* pcb) {
int max = 0, temp = -1;
statusConfirm(pcb);
for (int i = 0; i < JOBNUMBER; i++) {
if (strcmp(pcb[i].processStatus, WAIT) == 0) {
if ((currentTime - pcb[i].arriveTime) / pcb[i].runTime + 1 >= max) {
// 等待时间/要求服务时间+1 >=max?
max = (currentTime - pcb[i].arriveTime) / pcb[i].runTime + 1;
temp = i;
}
}
}
return temp;
}
//运行第一个到达的进程
void runFirstJob(struct PCB* pcb) {
pcb[0].startTime = currentTime;
int endTime = pcb[0].startTime + pcb[0].runTime;
strcpy(pcb[0].processStatus, RUN);
while (1) {
if (currentTime == endTime) {
pcb[0].endTime = endTime;
pcb[0].turnoverTime = pcb[0].endTime - pcb[0].arriveTime;
pcb[0].useWeightTurnoverTime = pcb[0].turnoverTime * 1.0 / pcb[0].runTime;
strcpy(pcb[0].processStatus, FINISH);
finishNumber++;
break;
}
else {
statusConfirm(pcb);
printJob(pcb);
currentTime++;
}
}
}
//比较各个进程之间的到达时间,按升序排列
void compare(struct PCB* pcb) {
for (int i = 0; i < JOBNUMBER; i++) {
int min = pcb[i].arriveTime;
int minIndex = i;
for (int j = i + 1; j < JOBNUMBER; j++) {
if (pcb[j].arriveTime < min) {
min = pcb[j].arriveTime;
minIndex = j;
}
}
struct PCB temp = pcb[i];
pcb[i] = pcb[minIndex];
pcb[minIndex] = temp;
}
for (int j = 0; j < 5; j++)
{
copy_pcb[j] = pcb[j];//对进程的初始化信息备份
}
}
//计算平均带权周转时间
float weightTurnoverTimeCount(struct PCB* pcb) {
float sum = 0.0;
for (int i = 0; i < JOBNUMBER; i++) {
sum += pcb[i].useWeightTurnoverTime;
}
return sum / JOBNUMBER;
}
//计算平均周转时间
float turnOverTimeCount(struct PCB* pcb) {
float sum = 0.0;
for (int i = 0; i < JOBNUMBER; i++) {
sum += pcb[i].turnoverTime;
}
return sum / JOBNUMBER;
}
//短进程优先调度
void runSPF(struct PCB* pcb)
{
int index = shortIndex(pcb);
strcpy(JobArray[indexJob++], pcb[index].jobName);
if (index == -1) //没有进程处于wait状态
printJob(pcb);
else {
pcb[index].startTime = currentTime;
pcb[index].endTime = pcb[index].startTime + pcb[index].runTime;
pcb[index].turnoverTime = pcb[index].endTime - pcb[index].arriveTime;
pcb[index].useWeightTurnoverTime = pcb[index].turnoverTime * 1.0 / pcb[index].runTime;
strcpy(pcb[index].processStatus, RUN);
while (1) {
statusConfirm(pcb);
if (currentTime == pcb[index].endTime) {
strcpy(pcb[index].processStatus, FINISH);
finishNumber++;
if (finishNumber == JOBNUMBER) {
printJob(pcb);
}
break;
}
else {
printJob(pcb);
currentTime++;
}
}
}
}
//时间片轮转调度
void runRR(int time_counter, struct PCB* pcb, struct PCB* copy_pcb)
{
int temp = time_counter;
int index = fastIndex(pcb);
strcpy(JobArray[indexJob++], pcb[index].jobName);
if (index == -1) //没有进程处于wait状态
printJob(pcb);
else {
if (pcb[index].start_flag == 0) //该条件成立则说明,该进程是第一次执行,记录开始执行时间
{
pcb[index].startTime = currentTime;
pcb[index].start_flag = 1;
}
if (pcb[index].runTime - time_counter > 0)//至少有两个时间片未执行
{
pcb[index].runTime = pcb[index].runTime - time_counter;
pcb[index].endTime = -1;
strcpy(pcb[index].processStatus, RUN);
pcb[index].arriveTime = currentTime + time_counter * (JOBNUMBER - finishNumber);
}
else if (pcb[index].runTime - time_counter == 0)
{
pcb[index].endTime = cur