进程调度算法C++实现

一、实验内容

1.编程实现处理机调度算法,算法包括:时间片轮转法,短进程优先算法,动态优先级算法。
2.可选择进程数量,即进程数目可动态变化。
3.主程序包括三种算法,执行时在主界面选择算法(可用函数实现),进入子页面后输入进程数(运行时间,优先数由随机函数产生),执行,显示结果。

二、算法思想

1.时间片轮转调度算法

算法思想:系统把所有的就绪进程按FCFS原则排成一个队列,
且规定一个时间片作为进程每次使用处理机的最长时间单位,
按时间片把处理机轮流分配给当前位于就绪队列队首的进程使用,当该进程的时间片用完以后,系统产生时钟中断,剥夺该进程的执行,将它送到就绪队列队尾,等待下一轮次的调度。同时处理机调度程序又去调度当前就绪队列的队首进程,也让它运行给定的时间片,如此循环往复。

2.最短进程调度算法

算法思想:根据进程的运行时间,确定进程的优先级,进程的运行时间越短,就越先被执行

3.动态优先数算法

可抢占方式的调度算法
若所有的进程具有相同的优先权初值,则按照FCFS算法,最先进入就绪队列的进程最先获得处理机。若所有的就绪进程具有各不相同的优先权初值,对于优先权初值低的进程,在等待足够的时间后,其优先权可能升为最高,从而获得处理机执行。
基本原则
(1)根据进程占有CPU时间多少来决定,当进程占有CPU时间愈长,那么,在它被阻塞之后再次获得调度的优先级就越低,反之,进程获得调度的可能性越大;
(2)根据进程等待CPU时间多少来决定,当进程在就绪队列中等待时间愈长,那么,在它被阻塞之后再次获得调度的优先级就越高,反之,进程获得调度的可能性越小。

三、实验代码

#include <iostream>
#include <cstring>
#include <queue>
#include <stdio.h>
#include <algorithm>

using namespace std;


/********************1-时间片轮转法*********************************/
struct PCB1 
{
    int name;           //定义进程号
    int arrivalTime;    // 到达时间
    int excutionTime;   //运行时间
    int restTime;       //剩余时间
    int state=0;        //进程的当前状态
    //运行1,就绪0,完成2 初始都是就绪状态
    //函数重载
    bool operator<(const PCB1 &obj) const
    {
        return arrivalTime < obj.arrivalTime;
    }
};
queue<PCB1> q;  //就绪队列
PCB1 P1[100];   
bool isStart = false;  //是否开始执行

void createP1(int proNum)
{
    //生成proNum个进程,并将进程加入队列当中
    for(int i=1;i<=proNum;i++)
    {
        PCB1 process;
        process.name = i;
        process.arrivalTime = rand()%20;  //生成1-20以内的随机整数
        process.excutionTime = rand()%100+20;  //运行时间20-120以内
        process.restTime = process.excutionTime;  //剩余时间
        P1[i] = process;
    }
}

void displayP1()
{
    //展示时间片轮转调度算法下的进程的运行情况
    queue<PCB1> q2;
    q2 = q;//当前队列的复制品
    if(isStart)  //开始执行
        printf("\n**********************程序开始运行**********************\n");
    else
        printf("\n**********************进程初始情况**********************\n");
    printf("进程号  到达时间/s 运行时间/s  剩余时间/s  当前状态\n");
    while (!q2.empty())
    {
        PCB1 currentP = q2.front();
        string state;
        q2.pop();
        if(currentP.state==0)
            state = "就绪状态";
        else if(currentP.state==1)
            state = "运行状态";
        else if(currentP.state==2)
            state = "完成状态";
        printf("%6d%8d%8d%14d%",currentP.name,currentP.arrivalTime,currentP.excutionTime,currentP.restTime);
        cout << "       "<< state << endl;
    }
    
}
//时间片轮转法调度算法
void RR(int proNum)
{
   //1-根据进程数创建进程的队列
   createP1(proNum);
   //2-根据进程的到达时间排序
   sort(P1+1, P1+proNum+1);
   //3-遍历进程数组,创建就绪队列
   for(int i=1;i<=proNum;i++)
        q.push(P1[i]);
   //4-打印初始状态
   displayP1();
   //5-执行进程
   isStart = true;  //开始执行进程,表示置为true
   int timeSlice=30;   //这里指定时间片为30秒
   cout << "时间片定义为30秒" << endl;
   while(!q.empty())  //就绪队列不为空,执行循环
   {
       q.front().state = 1;    //执行就绪队列队首的进程
       displayP1();              //展示进程的执行情况
       PCB1 currentPro = q.front();
       currentPro.restTime -= 30; //进程的剩余时间减少30秒
       q.pop();  //该进程出队
       if(currentPro.restTime <= 0)  //在该时间片中当前进程执行完毕
        {
            currentPro.state = 2;  //执行完毕状态
            continue;
        }
       else
        {
            currentPro.state = 0; //重新处于就绪状态
            q.push(currentPro);  //重新加入队列
        }
   }
   cout << "就绪队列为空,进程执行完毕!!\n" << endl;
}



/********************2-短进程优先算法*********************************/
struct PCB2
{
    int name;           //定义进程号
    int arrivalTime;    // 到达时间
    int excutionTime;   //运行时间
    int startTime;      //开始执行时间
    int finishTime;     //完成时间
    int TurnaroundTime; //周转时间
    //函数重载
    bool operator<(const PCB2 &obj) const
    {
        return excutionTime < obj.excutionTime;
    }
};
PCB2 P2[100];
bool isStart2 = false;

void createP2(int proNum)
{
    //创建进程
    for(int i=1;i<=proNum;i++)
    {
        PCB2 process;
        process.name = i;
        process.arrivalTime = rand()%20;  //生成1-20以内的随机整数
        process.excutionTime = rand()%100+20;  //运行时间20-120以内
        P2[i] = process;
    }
}

void displayP2(int proNum)
{
    //展示短进程优先调度算法下的进程的运行情况
    if(isStart2==false)  
    {
        printf("\n******************进程初始状态*****************\n");
        printf("进程号  到达时间/s 运行时间/s \n");
        for(int i=1;i<=proNum;i++)
        {
            printf("%6d%8d%8d\n",P2[i].name,P2[i].arrivalTime,P2[i].excutionTime);
        }
        printf("***********************************************\n");
        cout << "进程执行顺序如下:\n" << endl;
        int i;
        for(i=1;i<proNum;i++)
        {
            cout << P2[i].name << "-->";
        }
        cout << P2[i].name << endl;
        
    }
    else
    {
        printf("\n****************************进程运行情况*****************************\n");
        printf("进程号  到达时间/s 运行时间/s  开始执行时间/s  完成时间/s   周转时间/s\n");
        for(int i=1;i<=proNum;i++)
        {
            printf("%6d%8d%8d%16d%14d%10d\n",P2[i].name,P2[i].arrivalTime,P2[i].excutionTime,P2[i].startTime, P2[i].finishTime,P2[i].TurnaroundTime);
        }
        printf("*********************************************************************\n");
    }
}

void SPF(int proNum)
{
   //1-根据进程数创建进程
   createP2(proNum);
   //2-根据进程执行时间进行排序
   sort(P2+1, P2+proNum+1);
   //3-展示根据进程长短排序后的进程的情况,以及进程运行情况
   displayP2(proNum);
   //4-执行调度
   isStart2 = true;
   int T=P2[1].arrivalTime;
   for(int i=1;i<=proNum;i++)
   {
       //上一个进程的结束时间就是,下一个进程的开始时间
       P2[i].startTime=T;
       T += P2[i].excutionTime;
       P2[i].finishTime = T;
       P2[i].TurnaroundTime = P2[i].finishTime - P2[i].arrivalTime;//周转时间
   }
   //5-展示进程执行的情况
   displayP2(proNum);
}


/********************3-动态优先级算法*********************************/
struct PCB3
{
    int name;           //定义进程号
    int arrivalTime;    //进程到达的时间
    int excutionTime;   //运行时间
    int restTime;     //剩余完成时间
    int priority;       //优先数
    int state=0;          //进程的状态,未到达0 就绪1,执行2,完成3
    //函数重载
    bool operator<(const PCB3 &obj) const
    {
        return priority > obj.priority;  //优先数从高到低排序
    }
    
};
PCB3 P3[100];
bool isStart3=false;      //是否开始调度
int earlistTime=0x3f3f3f; //最早到达的进程·
int totalTime=0;
priority_queue<PCB3> que; //就绪 优先队列
queue<PCB3> finishedQue;  //已完成进程队列
queue<PCB3> initQue;     //未到达进程队列

void createP3(int proNum)
{
    for(int i=1;i<=proNum;i++)
    {
        PCB3 process;
        process.name = i;
        process.arrivalTime = rand()%5+1;  //到达时间在5以内
        process.excutionTime = rand()%5+1;  //运行时间在5以内
        process.priority = rand()%10;   //优先数
        process.restTime = process.excutionTime;
        P3[i] = process;
        if(process.arrivalTime < earlistTime)
            earlistTime = process.arrivalTime;
        totalTime += process.excutionTime;

    }
    
}

void displayP3(int proNum)
{
    if(!isStart3)
    {
        printf("\n******************进程初始状态*****************\n");
        printf("进程号  到达时间/s 运行时间/s  优先数    状态\n");
        for(int i=1;i<=proNum;i++)
        {
             printf("%6d%8d%8d%12d%10d\n",P3[i].name,P3[i].arrivalTime,P3[i].excutionTime,P3[i].priority,P3[i].state);
        }
        printf("***********************************************\n");
    }
}
void displayQue(queue<PCB3> q)
{
    while(!q.empty())
    {
        PCB3 currentProcess = q.front();
        q.pop();
        printf("%6d%8d%8d%12d%10d\n",currentProcess.name,currentProcess.arrivalTime,currentProcess.excutionTime,currentProcess.priority,currentProcess.state);
    }
}

void displayQue(priority_queue<PCB3> q)
{
    while(!q.empty())
    {
        PCB3 currentProcess = q.top();
        q.pop();
        printf("%6d%8d%8d%12d%10d\n",currentProcess.name,currentProcess.arrivalTime,currentProcess.excutionTime,currentProcess.priority,currentProcess.state);
    }
}

bool cmp(PCB3 a, PCB3 b)
{
    return a.arrivalTime < b.arrivalTime;
}
//优先数是动态变化的,每次取优先级最高的那个进程,等待时间增加,处于就绪状态的进程的优先数增加
//将处理机的调度权限分配给优先数较高的进程
//进行抢占式调度
//以时间为主线
//执行时间越长,优先数会下降
//优先数相同时,根据到达时间,先来先服务
//就绪队列中优先级最高的进程
//这个进程必须是已经到达的
//给已经到达并处于等待状态的进程的优先数+1
//给正在运行的进程优先数-1
//创建一个就绪队列,这个就绪队列是优先队列,进程数高的是靠前的
//从到达时间最早的那个进程开始,设为开始时间,这个进程先入队
void DP(int proNum)
{
   //1-创建进程
    createP3(proNum);
   //2-根据到达时间排个顺序
   sort(P3+1, P3+proNum+1,cmp);
   //3-展示进程的初始情况
   cout << "状态说明:" << endl;
   cout << "0:未到达, 1:就绪状态,2:运行状态,3:完成状态" << endl;
   displayP3(proNum);
    //将进程加入一个队列(代表未执行进程)该队列包含所有的未执行进程
    for(int i=1;i<=proNum;i++)
    {
        initQue.push(P3[i]);  //加入队列
    }
   //4-进行调度
    isStart3 = true;
    cout << "最早开始时间为:第" << earlistTime << "秒" << endl;
    cout << "完成时间为:第" << earlistTime+totalTime << "秒" << endl;
    for(int t=earlistTime; t<=(earlistTime+totalTime);t++)
    {
       cout << "当前时间为:第" << t << "秒!" << endl;
        //4-1 判断未执行进程队列队首进程是否可以处于就绪状态
        if(!initQue.empty() && initQue.front().arrivalTime==t)
        {
            initQue.front().state=1; //就绪状态
            que.push(initQue.front());  //加入就绪队列
            initQue.pop(); //出队
        }
        //4-2 每秒钟要进行一次所有进程状态的展示
        printf("****************************进程运行情况*****************************\n");
        printf("进程号  到达时间/s 运行时间/s  优先数  状态\n");
        //4-2-1 展示initQue中剩余进程的状态(未执行进程)
        if(!initQue.empty())   
            displayQue(initQue);         
        //4-3 若就绪队列不为空,从就绪队列中取出当前优先数最高进程,让它处于执行状态
        PCB3 runProcess;
        if(!que.empty())
        {
            runProcess = que.top();  //就绪队列为优先队列
            que.pop();//出队
            runProcess.state = 2; //处于运行状态
            runProcess.priority--;//优先数减1
            runProcess.restTime--; //剩余完成时间减1
            //4-2-2 展示正在执行的进程的情况(正在执行进程)
            printf("%6d%8d%8d%12d%10d\n",runProcess.name,runProcess.arrivalTime,
            runProcess.excutionTime,runProcess.priority,runProcess.state);
        }
        else
        {
            runProcess.name = 0;
        }
        //4-4 遍历就绪队列中的其他每一个进程,将它们的优先数加1
        PCB3 process;
        priority_queue<PCB3> temporaryQue;  //临时的优先队列
        while(!que.empty())
        {
            process = que.top();  //获取最顶的元素
            process.priority += 1; //优先数加1
            temporaryQue.push(process);
            que.pop();
        }
        que = temporaryQue;  //重新赋值给que
        //4-2-3 展示就绪队列中所有进程信息 (就绪进程)
        if(!que.empty())
            displayQue(que);
        //4-2-4 展示完成队列中所有的进程信息(完成进程)
        if(!finishedQue.empty())
            displayQue(finishedQue);
        //4-5 判断正在运行的进程在这一秒后否运行完毕,如果运行完毕,置状态为3,加入完成队列,
        //如果没有运行完毕,置状态为1,加入就绪队列
        if(runProcess.name == 0)
        {
            //说明原来的就绪队列是空的
            cout << "就绪队列为空\n" << endl;
        }
        else
        {
            if(runProcess.restTime==0)
            {
                runProcess.state = 3;
                finishedQue.push(runProcess);
            }
            else
            {
                runProcess.state = 1;
                que.push(runProcess);
            }
        }
    }
    printf("进程调度完毕!");
}



//调度程序
void dispatch()
{
    /*
    函数名称:调度算法模拟函数
    */
   int proNum;       //进程的数量
   int choice;       //功能选择
   char isContinue; //是否继续
   do{
        printf("    **                       输入 1-时间片轮转法                           *\n");
        printf("    **                       输入 2-短进程优先算法                         *\n");
        printf("    **                       输入 3-动态优先级算法                         *\n");
        printf("    **                       输入 0-退出该程序                             *\n");
        printf("\n提示:请根据自己的需求选择相应的操作数:\n");
        cin >> choice ;
        /*提示输入字母,用switch语句存入到case中*/
        switch(choice)
        {
            case 0:
                break;
            case 1:
                    printf("您选择的是时间片轮转法\n\n");
                    printf("请输入进程的数量:\n");
                    cin >> proNum;
                    RR(proNum);
                    break;
            case 2:
                    printf("\n您选择的是短进程优先算法\n\n");
                    printf("请输入进程的数量:\n");
                    cin >> proNum;
                    SPF(proNum);
                    break;
            case 3:
                    printf("\n您选择的是动态优先级调度算法\n\n");
                    printf("请输入进程的数量:\n");
                    cin >> proNum;
                    DP(proNum);
                    break;
            default:
                    printf("\n你的输入有误,请确定是从0到3之间进行输入,O(∩_∩)O谢谢\n");
                    break;
        }
        printf("\n是否继续操作(y/n) ?");
        fflush(stdin);
        isContinue=getchar();
    }while(isContinue=='y'||isContinue=='Y');
}


int main()
{
    printf("\t\t*          调度算法模拟          *\n");
    dispatch();
    return 0;
}

  • 3
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值