实验2 进程调度

本文档介绍了如何实现四种调度算法(PSA、FCFS、SJF和MFQ),包括优先级调度、先来先服务、短作业优先及多级反馈队列,通过C++代码展示了从数据输入到算法运行的全过程,包括进程创建、菜单选择、调度执行和性能统计。
摘要由CSDN通过智能技术生成
#include<bits/stdc++.h>
#define W 1
#define R 2
#define F 3
#define PS 1
#define FCFS 2
#define SJF 3
#define MFQ 4
using namespace std;
const int maxn = 10+1;
const char State[maxn][maxn]={"0", "Wait", "Run", "Finish"};//进程状态
int choose;//用户选择
int TotPCB;//总进程个数
int NOWTIME;//模拟系统时间

typedef struct pcb
{
    char name[maxn];
    int priority, arriveTime, serveTime, AllCPUtime;
    //分别为优先级,就绪时间,服务时间,已占用进程时间
    int completeTime;
    int state;
}*PCB, pb;

typedef struct Pr//进程
{
    PCB Pcb;//该结点的代表的进程控制块
    Pr *nex;//该节点的下一个结点
}*PCBQ;//进程控制块队列

PCBQ DataQ;//读入的数据
PCBQ ReadyQ;//就绪队列
PCBQ PCBBank;;//还在系统中进程队列

void outmenu();//菜单

//以下是算法
bool PSA();//优先级调度算法
bool FCFSA();//先来先服务调度算法
bool SJFA();//短作业优先调度算法
bool MFQA();//多级反馈队列调度算法

//以下是操作
void Init();//初始化
void InsertPCB(PCBQ, PCB);//将PCB插入指定队列
PCBQ FindPCB();//在当前NOWTIME条件下在DataQ中寻找有没有新的进程到达
void DisPlay(PCB);//显示该进程的信息
void View(PCBQ);//显示该队列的信息
bool IsEmpty(PCBQ);//检查队列是否为空
void OutTimeConsume();//输出平均周转时间和带权平均周转时间
PCBQ Pop(PCBQ);

int main()
{
    freopen("data.in","r", stdin);
    Init();
    puts("请输入进程个数");
    scanf("%d", &TotPCB);
    puts("请分别输入这些进程的进程名、就绪时刻、服务时间、优先级");
    for(int i=1; i<=TotPCB; ++i)
    {
        PCB p = (PCB)malloc(sizeof(pb));
        scanf("%s %d %d %d", p->name, &p->arriveTime, &p->serveTime, &p->priority);
        p->AllCPUtime = 0;
        p->completeTime = -1;
        p->state = W;//初始没有
        InsertPCB(DataQ, p);
    }
    outmenu();
    View(DataQ);
    scanf("%d", &choose);
    while (choose>4||choose<1)
    {
        puts("请输入正确的算法编号");
        scanf("%d", &choose);
    }
    
    bool flag = false;
    switch (choose)
    {
    case PS:
        flag = PSA();
        break;
    case FCFS:
        flag = FCFSA();
        break;
    case SJF:
        flag = SJFA();
        break;
    case MFQ:
        flag = MFQA();
        break;
    default:
        puts("something wrong");
        break;
    }
    if(flag) puts("调用成功");
    else{
        puts("错误退出");
    }
    return 0;
}

void outmenu()
{
    puts("本调度系统均采用非抢占调度,以下是可供调度算法,请选择");
    puts("1.最高优先数优先算法\n2.先来先服务算法\n3.短作业优先算法\n4.多级反馈\n");
}

bool PSA()
{
    puts("现在在调用最高优先数优先算法\n");
    while (!IsEmpty(DataQ)||!IsEmpty(ReadyQ))//当没有进程再来的时候并且就绪队列进程都运行完就结束循环
    {
        //寻找当前系统时间有没有新进程到达
        PCBQ NewPCB;
		while((NewPCB = FindPCB()) != NULL)
        {           
			PCBQ node = (PCBQ)malloc(sizeof(Pr));
			node->Pcb = NewPCB->Pcb;
            node->nex = NULL;
            //按照当前的算法将新进程插入就绪队列
			PCBQ head = ReadyQ;
			while(head->nex&&node->Pcb->priority<=head->nex->Pcb->priority) head = head->nex;
            node->nex = head->nex;
            head->nex = node;
		}
        if(IsEmpty(ReadyQ)) ++NOWTIME;//模拟系统时间片
        else{
            //就绪队列不为空要进行调度
            PCBQ node = Pop(ReadyQ);
            node->Pcb->state = R;
            printf("进程%s信息入下\n", node->Pcb->name);
            DisPlay(node->Pcb);
            puts("");
            puts("就绪队列信息如下");
            View(ReadyQ);
            puts("");
            puts("各个进程的PCB如下");
            View(PCBBank);
            puts("");
            node->Pcb->state = F;
            node->Pcb->AllCPUtime += node->Pcb->serveTime;
            node->Pcb->completeTime = NOWTIME+node->Pcb->serveTime;
            NOWTIME += node->Pcb->serveTime;
        }
    }
    puts("结束以下是结果");
    View(PCBBank);
    OutTimeConsume();
    return true;
}

bool FCFSA()
{
    puts("现在在调用先来先服务算法");
     while (!IsEmpty(DataQ)||!IsEmpty(ReadyQ))//当没有进程再来的时候并且就绪队列进程都运行完就结束循环
    {
        //寻找当前系统时间有没有新进程到达
        PCBQ NewPCB;
		while((NewPCB = FindPCB()) != NULL)
        {
			PCBQ node = (PCBQ)malloc(sizeof(Pr));
			node->Pcb = NewPCB->Pcb;
            node->nex = NULL;
            //按照当前的算法将新进程插入就绪队列
            PCBQ head = ReadyQ;
            while (head->nex) head = head->nex;
            head->nex = node;
		}

        if(IsEmpty(ReadyQ)) ++NOWTIME;//模拟系统时间片
        else{
            //就绪队列不为空要进行调度
            PCBQ node = Pop(ReadyQ);
            node->Pcb->state = R;
            printf("进程%s信息入下\n", node->Pcb->name);
            DisPlay(node->Pcb);
            puts("");
            puts("就绪队列信息如下");
            View(ReadyQ);
            puts("");
            puts("各个进程的PCB如下");
            View(PCBBank);
            puts("");
            node->Pcb->state = F;
            node->Pcb->AllCPUtime += node->Pcb->serveTime;
            node->Pcb->completeTime = NOWTIME+node->Pcb->serveTime;
            NOWTIME += node->Pcb->serveTime;
        }
    }
    puts("结束以下是结果");
    View(PCBBank);
    OutTimeConsume();
    return true;
}

bool SJFA()
{
    puts("现在在调用短作业优先算法");
     while (!IsEmpty(DataQ)||!IsEmpty(ReadyQ))//当没有进程再来的时候并且就绪队列进程都运行完就结束循环
    {
        //寻找当前系统时间有没有新进程到达
        PCBQ NewPCB;
		while((NewPCB = FindPCB()) != NULL)
        {
			PCBQ node = (PCBQ)malloc(sizeof(Pr));
			node->Pcb = NewPCB->Pcb;
            node->nex = NULL;
            //按照当前的算法将新进程插入就绪队列
			PCBQ head = ReadyQ;
			while(head->nex&&node->Pcb->serveTime>=head->nex->Pcb->serveTime) head = head->nex;
            node->nex = head->nex;
            head->nex = node;
		}

        if(IsEmpty(ReadyQ)) ++NOWTIME;//模拟系统时间片
        else{
            //就绪队列不为空要进行调度
            PCBQ node = Pop(ReadyQ);
            node->Pcb->state = R;
            printf("进程%s信息入下\n", node->Pcb->name);
            DisPlay(node->Pcb);
            puts("");
            puts("就绪队列信息如下");
            View(ReadyQ);
            puts("");
            puts("各个进程的PCB如下");
            View(PCBBank);
            puts("");
            node->Pcb->state = F;
            node->Pcb->AllCPUtime += node->Pcb->serveTime;
            node->Pcb->completeTime = NOWTIME+node->Pcb->serveTime;
            NOWTIME += node->Pcb->serveTime;
        }
    }
    puts("结束以下是结果");
    View(PCBBank);
    OutTimeConsume();
    return true;
}

bool MFQA()
{
    puts("现在在调用多级反馈队列算法");
    //因为使用多级反馈,所以还要再增加两个,而ReadQ已经初始化完成那么
    //新的就绪队列和ReadQ一样就可以
    PCBQ ReadyQ2 = (PCBQ)malloc(sizeof(Pr));
    PCBQ ReadyQ3 = (PCBQ)malloc(sizeof(Pr));
    ReadyQ2->Pcb = ReadyQ3->Pcb = ReadyQ->Pcb = NULL;
    ReadyQ3->nex = ReadyQ2->nex = ReadyQ->nex = NULL;

    while (!IsEmpty(DataQ)||!IsEmpty(ReadyQ)||!IsEmpty(ReadyQ2)||!IsEmpty(ReadyQ3))//当没有进程再来的时候并且就绪队列进程都运行完就结束循环
    {
        //寻找当前系统时间有没有新进程到达
        PCBQ NewPCB;
		while((NewPCB = FindPCB()) != NULL)
        {
			PCBQ node = (PCBQ)malloc(sizeof(Pr));
			node->Pcb = NewPCB->Pcb;
            node->nex = NULL;
            //按照当前的算法将新进程插入就绪队列
			PCBQ head = ReadyQ;
			while(head->nex&&node->Pcb->priority<=head->nex->Pcb->priority) head = head->nex;
            node->nex = head->nex;
            head->nex = node;
		}
        //队列时间片设置123
        if(IsEmpty(ReadyQ)&&IsEmpty(ReadyQ2)&&IsEmpty(ReadyQ3)) ++NOWTIME;//模拟系统时间片
        else{
            //就绪队列不为空要进行调度
            PCBQ node = NULL;
            int time = 0;
            if(!IsEmpty(ReadyQ)){
                time = 1;
                node = Pop(ReadyQ);
            }
            else if(!IsEmpty(ReadyQ2)){
                time = 2;
                node = Pop(ReadyQ2);
            }
            else if(!IsEmpty(ReadyQ3)){
                time = 3;
                node = Pop(ReadyQ3);
            }
            node->Pcb->state = R;
            printf("进程%s信息入下\n", node->Pcb->name);
            DisPlay(node->Pcb);
            puts("");
            puts("就绪队列1信息如下");
            View(ReadyQ);
            puts("");
            puts("就绪队列2信息如下");
            View(ReadyQ2);
            puts("");
            puts("就绪队列3信息如下");
            View(ReadyQ3);
            puts("");
            puts("各个进程的PCB如下");
            View(PCBBank);
            puts("");
            cout<<"time1 = "<<time<<endl;
            int rest = node->Pcb->serveTime-node->Pcb->AllCPUtime;
            if(rest>=time) node->Pcb->AllCPUtime += time, NOWTIME += time;
            else node->Pcb->AllCPUtime += rest, NOWTIME += rest;
            if(node->Pcb->AllCPUtime==node->Pcb->serveTime){
                node->Pcb->completeTime = NOWTIME;
                node->Pcb->state = F;
            }
            if(node->Pcb->state==F) continue;
            node->Pcb->state = W;
            // cout<<"time1 = "<<time<<endl;
            switch (time)
            {
            case 1:
                InsertPCB(ReadyQ2, node->Pcb);
                break;
            case 2:
                InsertPCB(ReadyQ3, node->Pcb);
                break;
            case 3:
                InsertPCB(ReadyQ3, node->Pcb);
                break;
            default:
                puts("something wrong in MFQA");
                puts("请联系作者来解决");
                return false;
                break;
            }
        }
    }
    View(PCBBank);
    OutTimeConsume();
    return true;
}

void Init(){
    //方便操作建立表头结点
    PCBBank = (PCBQ)malloc(sizeof(Pr));
	PCBBank->nex = NULL;
	PCBBank->Pcb = NULL;
	ReadyQ = (PCBQ)malloc(sizeof(Pr));
	ReadyQ->nex = NULL;
	ReadyQ->Pcb = NULL;
    DataQ = (PCBQ)malloc(sizeof(Pr));
    DataQ->nex = NULL;
    DataQ->Pcb = NULL;
	NOWTIME = 0;
}

void InsertPCB(PCBQ q, PCB node)
{
    PCBQ head = q;
    while (head->nex) head = head->nex;
    PCBQ t = (PCBQ)malloc(sizeof(Pr));
    t->Pcb = node;
    t->nex = NULL;
    head->nex = t;
}

PCBQ FindPCB()
{
    PCBQ head = DataQ;
    PCBQ ret = NULL;
    if(head->nex && head->nex->Pcb->arriveTime<=NOWTIME)
    {
        ret = (PCBQ)malloc(sizeof(Pr));
        ret->Pcb = head->nex->Pcb;
        ret->nex = NULL;
        InsertPCB(PCBBank, ret->Pcb);
        PCBQ t = head->nex;
        head->nex = t->nex;
        free(t);
    }
    return ret;
}

void DisPlay(PCB node){
    printf("进程名:%s 优先级:%d 到达时间:%d 需要服务时间:%d 完成时间:%d 状态:%s\n", 
    node->name, node->priority, 
    node->arriveTime, node->serveTime, 
    node->completeTime, State[node->state]);
}

void View(PCBQ head){
    PCBQ node = head;
    if(node->nex == NULL){
        puts("该就绪队列暂时为空");
        return;
    }
    puts("进程名  优先级  到达时间  需要服务时间  完成时间  状态  ");
    while (node->nex)
    {
        printf("%-7s %-7d %-9d %-13d %-9d %-8s\n", 
        node->nex->Pcb->name, node->nex->Pcb->priority, 
        node->nex->Pcb->arriveTime, node->nex->Pcb->serveTime, 
        node->nex->Pcb->completeTime, State[node->nex->Pcb->state]);
        node = node->nex;
    } 
}

bool IsEmpty(PCBQ head){
    return head->nex==NULL;
}

void OutTimeConsume()
{
    double t = 0, w = 0;
    PCBQ q = PCBBank;
    while (q->nex)
    {
        t += q->nex->Pcb->completeTime-q->nex->Pcb->arriveTime;
        w += (q->nex->Pcb->completeTime-q->nex->Pcb->arriveTime)*1.0/(1.0*q->nex->Pcb->serveTime);
        q = q->nex;
    }
    t /= (1.0*TotPCB);
    w /= (1.0*TotPCB);
    printf("平均周转时间为:%f 带权平均周转时间为:%f\n", t, w);
}

PCBQ Pop(PCBQ head)
{
    PCBQ ret = (PCBQ)malloc(sizeof(Pr));
	PCBQ p = head->nex;
	if(p){
		head->nex = p->nex;
		ret->Pcb = p->Pcb;
        ret->nex = NULL;
		free(p);
	}
	return ret;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值