操作系统——时间片轮转调度算法(RR)

本文详细解析了时间片轮转(RR)调度算法的流程图,涉及数据结构、参数设置、关键函数如进程排序、周转时间计算,以及如何通过调整时间片大小影响调度效果。重点讨论了算法效率与时间片选择的关系,并提供了实例分析。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

RR算法总体思路流程图

主要数据结构及参数

typedef struct PCB
{
    char name;//进程名
    int arrive_time;//到达时间
    float cpu_burst;//服务时间
    float surplus;//剩余服务时间
    int start_time;//开始执行时间
    int finish_time;//完成时间
    int wait_time;//等待时间
    float turn_time;//周转时间
    float weighted_ttime;//带权周转时间
    bool over;//标记进程是否执行完毕
    float response;//响应比
}PCB;//定义进程数据结构

int pcb_num;//进程个数

int time_p;//时间片大小

主要函数

//将进程按照到达先后顺序排序
void sort_arrival(PCB pcb[],int pcb_num){}

//计算周转时间和带权周转时间
void calculator_rr(PCB pcb[],int pcb_num){}

//RR调度算法
void rr(PCB pcb[],int pcb_num,float time_p){}

//计算平均周转时间、平均带权周转时间、平均等待时间
void cal_avg(PCB pcb[],int pcb_num){}

//输出各进程
void show(PCB pcb[],int pcb_num){}

//主函数测试RR调度算法
int main(){}

①sort_arrival()函数:输入进程顺序表pcb[]和进程个数pcb_num作为函数参数,然后将顺序表pcb[]按照到达的先后顺序排序。

②calculator_rr()函数:输入进程顺序表pcb[]和进程个数pcb_num作为函数参数,用于在rr()函数中反复调用,根据顺序表pcb[]中已知的到达时间、完成时间、服务时间,计算周转时间和带权周转时间

③rr()函数:输入进程顺序表pcb[]和进程个数pcb_num作为函数参数,主要是实现RR调度算法,将经RR调度算法计算后的开始执行时间、完成时间、等待时间、周转时间、带权周转时间存入进程顺序表中。

④cal_avg()函数:输入进程顺序表pcb[]和进程个数pcb_num作为函数参数,通过进程顺序表中的等待时间、周转时间、带权周转时间计算出平均等待时间、平均周转时间、平均带权周转时间,然后输出。

⑤show()函数:输入进程顺序表pcb[]和进程个数pcb_num作为函数参数,以表格的形式输出进程顺序表中的各参数信息。

⑥main()函数:主函数中输入进程顺序表,测试FCFS调度函数和SJF调度函数,输出测试结果。

代码

#include<iostream>
#include<iomanip>
#include<queue>
#include<algorithm>

using namespace std;

typedef struct PCB
{
    char name;//进程名
    int arrive_time;//到达时间
    float cpu_burst;//服务时间
    float surplus;//剩余服务时间
    int start_time;//开始执行时间
    int finish_time;//完成时间
    int wait_time;//等待时间
    float turn_time;//周转时间
    float weighted_ttime;//带权周转时间
    bool over;//标记进程是否执行
}PCB;//定义进程数据结构

//将进程按照到达先后顺序排序
void sort_arrival(PCB pcb[],int pcb_num)
{
    PCB temp;
    for(int i=0;i<pcb_num-1;i++)
    {
        for(int j=i+1;j<pcb_num;j++)
        {
            if(pcb[i].arrive_time>pcb[j].arrive_time)
            {
                temp = pcb[i];
                pcb[i] = pcb[j];
                pcb[j] = temp;
            }
        }
    }
}

//计算周转时间和带权周转时间
void calculator_rr(PCB pcb[],int pcb_num)
{
    for(int i=0;i<pcb_num;i++)
    {
        pcb[i].turn_time = pcb[i].finish_time-pcb[i].arrive_time;//周转时间 = 完成时间-到达时间
        pcb[i].weighted_ttime = pcb[i].turn_time/pcb[i].cpu_burst;//带权周转时间 = 周转时间/服务时间
    }
}

//RR调度算法
void rr(PCB pcb[],int pcb_num,float time_p)
{
    for(int i=0;i<pcb_num;i++)
    {
        pcb[i].surplus = pcb[i].cpu_burst;
        pcb[i].finish_time = 0;
        pcb[i].start_time = 0;
        pcb[i].turn_time = 0;
        pcb[i].wait_time = 0;
        pcb[i].weighted_ttime = 0;
    }//初始化进程信息
    queue<int> wait_q;//定义进程等待队列
    sort_arrival(pcb,pcb_num);//将所有进程按照到达的先后顺序排列
    int t = pcb[0].arrive_time;//时间从第一个进程到达开始
    wait_q.push(0);//将第一个进程加入等待队列

    while(wait_q.empty() == false)
    {
        int t0 =t;//记录需要进行进程切换的时刻
        int run;
        run = wait_q.front();
        wait_q.pop();

        if(pcb[run].over == false)//进程第一次执行时
        {
            pcb[run].start_time = t;//记录第一次开始执行的时间
            pcb[run].wait_time = pcb[run].wait_time+t-pcb[run].arrive_time;//累加计算等待时间
            pcb[run].over = true;
        }
        else//进程非第一次执行时
        {
            pcb[run].wait_time = pcb[run].wait_time+t-pcb[run].finish_time;//累加计算等待时间
        }

        t = t+min(pcb[run].surplus,time_p);//将时间切换到下个时间片,或进程执行完毕
        pcb[run].finish_time = t;//更新每次进程执行结束的时间
        pcb[run].surplus = pcb[run].surplus-min(pcb[run].surplus,time_p);//更新进程剩余服务时间

        if(t0<pcb[pcb_num-1].arrive_time)
        {
            for(int i=0;i<pcb_num;i++)
            {
                if(pcb[i].arrive_time>t0 && pcb[i].arrive_time<=t)
                {
                    wait_q.push(i);
                }
            }//将所有在t0-t时间内到达的进程按照到达的先后顺序加入等待队列
        }
        if(pcb[run].surplus != 0)
        {
            wait_q.push(run);//若进程执行完毕则不再加入等待队列
        }
    }

    calculator_rr(pcb,pcb_num);//计算进程周转时间、带权周转时间
}


//计算平均周转时间、平均带权周转时间、平均等待时间
void cal_avg(PCB pcb[],int pcb_num)
{
    float sum1 = 0,sum2 = 0, sum3 = 0;
    float avg_turn, avg_weight, avg_wait;
    for(int i=0;i<pcb_num;i++)
    {
        sum1 = sum1+pcb[i].turn_time;
        sum2 = sum2+pcb[i].weighted_ttime;
        sum3 = sum3+pcb[i].wait_time;
    }
    avg_turn = sum1/pcb_num;
    avg_weight = sum2/pcb_num;
    avg_wait = sum3/pcb_num;
    cout<<"平均周转时间为:"<<avg_turn<<endl;
    cout<<"平均带权周转时间为:"<<avg_weight<<endl;
    cout<<"平均等待时间为:"<<avg_wait<<endl;
}

//输出各进程
void show(PCB pcb[],int pcb_num)
{
    cout<<"-----------------------------------------------------------------------------"<<endl;
    cout<<"进程名|到达时间|服务时间|开始执行时间|完成时间|周转时间|带权周转时间|等待时间"<<endl;
    cout<<"-----------------------------------------------------------------------------"<<endl;
    for(int i=0;i<pcb_num;i++)
    {
        cout<<pcb[i].name;
        cout<<"\t"<<pcb[i].arrive_time;
        cout<<"\t"<<pcb[i].cpu_burst;
        cout<<"\t"<<"\t"<<pcb[i].start_time;
        cout<<"\t"<<pcb[i].finish_time;
        cout<<"\t"<<pcb[i].turn_time;
        cout<<"\t"<<setprecision(3)<<pcb[i].weighted_ttime;
        cout<<"\t"<<pcb[i].wait_time<<endl;
    }
}

//主函数测试RR调度算法
int main()
{
    int pcb_num;//进程个数

    cout<<"请输入进程总个数:"<<endl;
    cin>>pcb_num;
    PCB pcb[pcb_num];
    for(int i=0;i<pcb_num;i++)
    {
        cout<<"请输入进程名:";
        cin>>pcb[i].name;//输入各进程名
        cout<<"请输入进程到达时间:";
        cin>>pcb[i].arrive_time; //输入各进程的到达时间
        cout<<"请输入进程需要服务的时间:";
        cin>>pcb[i].cpu_burst; //输入各进程需要服务的时间
        pcb[i].over = false;//初始时,所有进程执行状态都为false
        pcb[i].surplus = pcb[i].cpu_burst;//初始时,所有进程剩余服务时间都为服务时间
        pcb[i].finish_time = 0;
        pcb[i].start_time = 0;
        pcb[i].turn_time = 0;
        pcb[i].wait_time = 0;
        pcb[i].weighted_ttime = 0;
    }

    cout<<"--------------------------------"<<endl;
    cout<<"          RR调度结果           "<<endl;
    cout<<"--------------------------------"<<endl;
    int time_p;//时间片大小
    bool goon = true;
    while(goon == true)
    {
        cout<<"请输入时间片大小:";
        cin>>time_p;
        rr(pcb,pcb_num,time_p);
        show(pcb,pcb_num);
        cout<<endl;
        cal_avg(pcb,pcb_num);
        cout<<"是否继续测试RR调度结果(是则输入1,否则输入0):";
        cin>>goon;
    }
    return 0;
}

结果

结果分析

时间片轮转RR调度算法很大程度上取决于时间片大小的选取,时间片的大小直接决定了时间片轮转RR调度算法的效率,时间片选取过小,会频繁发生终端,需要不断进行上下文的切换,严重增加了系统的开销;时间片选取过大则时间片轮转RR调度算法直接退化为先来先服务FCFS调度算法。从表格可以看出,时间片轮转RR调度算法的各参数值都较高,效率较其他算法不算高,而且明显时间片轮转RR调度算法对时间片的选取要求较高,需要实现知道各进程的参数情况才能够选取合适的时间片大小。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值