进程调度—时间片轮转和先来先服务

1、先来先服务(first-come first-server)

它是最简单的非抢占式的进程调度算法,进程按照它们请求cpu的顺序使用cpu,当第一个作业从外部进入系统,就立即运行它所需要运行的时间。不会中断该作业。当其他作业进入时,它们就被安排到队列的尾部。当正在运行的进程被阻塞时,队列中的第一个进程接着运行。在被阻塞的进程重新变为就绪状态,排到队列的末尾,就像新来到的作业一样。

2、时间片轮转(RR)

它是一种最古老,最简单,最公平且使用最广的算法。每个进程被分配一个时间段,称它为时间片,即允许进程运行的时间。如果在时间片结束时进程还在进行,则cpu将被剥夺并分配给另一个进程。如果进程在结束前阻塞或结束,则cpu当即进行切换。当进程用完它的时间片后,它被移到队列的末尾。直到进程运行结束,它才从队列中移出。

以下代码演示了这两个进程调度算法,程序将从文件读取进程信息,在进程调度结束后,将调度结果输入到文件中

#include<stdio.h>
#include<stdlib.h>
#define N 50
struct PCB      //定义进程控制块
{   int name;   //进程名
    int runFlag;//判断进程是否已结束
    int startFlag;//判断进程是否是首次进行
    int  ArriveTime;  //到达时间
    int  StartTime;  //进程开始时间
    int  FinishTime;  //进程结束时间
    int  ServiceTime;   //服务时间
    int serviceTime1; //还需服务的时间
    float WholeTime;//周转时间
    float WeightWholeTime;//带权周转时间
}pcbs[N];
double x=0,y=0;//用于统计总的周转时间,总的带权周转时间
int i;
int time=0;   //计时器
int Round=2;//时间片
float averageWholeTime=0;//平均周转时间
float averageWeightWhole=0;//平均带权周转时间
int count_line(char* filepath){//统计文件里的进程数
    int count=0;
    int flag=0;
    FILE *fp=fopen(filepath,"r");
    if(!fp){
        printf("can't open file!");
        return 0;
    }
    while(!feof(fp)){
        flag=fgetc(fp);
        if(flag=='\n')count++;
    }
    int line=count+1;
    return line;
}
int charge(){//判断是否全部进程都执行完毕
    int k;
    int n=count_line("C:\\Users\\12280\\Desktop\\进程.txt");//获取文件中有几个进程
    int size=3*n;//文件里一行有3个数值,分别表示进程名,进程到达时间,进程运行时间,所以将3*行数,用于遍历所以完整的进程
    int flag=0;
    for(i=0;i<size;i+=3){
        if(pcbs[i].runFlag==0){//判断进程是否已经结束
            flag=1;
            return flag;
            break;
        }else{
            flag=0;
        }
    }
    return flag;
}
void run_RR(){//时间片调度算法函数
    int n=count_line("C:\\Users\\12280\\Desktop\\进程.txt");//获取文件中有几个进程
    int size=3*n;//文件里一行有3个数值,分别表示进程名,进程到达时间,进程运行时间,所以将3*行数,用于遍历所以完整的进程
    time=pcbs[i].ArriveTime;
    while(charge())
    {
        for(i=0;i<size;i+=3){
            if(pcbs[i].ArriveTime>time){//进程到达时间大于现在的时间,则进程从到达时间开始运行,否则从当前时间运行
                time=pcbs[i].ArriveTime;
            }
            if(pcbs[i].runFlag==0){//判断进程是否结束,若已结束,则开始下一个进程,否则执行当前进程
                if(pcbs[i].startFlag==0){
                    pcbs[i].StartTime=time;
                    pcbs[i].startFlag=1;
            }
            printf("--->时刻:%d,  正在运行的作业:%d\n",time,pcbs[i].name);
            if(pcbs[i].serviceTime1>Round){
                    pcbs[i].serviceTime1=pcbs[i].serviceTime1-Round;//如果服务时间大于时间片,运行一次后,减去一个时间片的时间
                    time=time+Round;
                }else if(pcbs[i].serviceTime1==Round){//如果剩余服务的时间刚刚好等于时间片的时间,则结束时间为当前时间加上时间片的时间
                    time=time+Round;
                    pcbs[i].FinishTime=time;
                    pcbs[i].runFlag=1;//并标志此进程已结束
                }else{
                    time=pcbs[i].serviceTime1+time;//如果剩余服务的时间小于时间片的时间,则结束时间为当前时间加上剩余服务时间
                    pcbs[i].FinishTime=time;
                    pcbs[i].runFlag=1;//并标注此进程已结束
                }
            }
        }
    }
    printf("hello");
}
int poutput() /*调度结果输出*/
{
    int i;
    int n=count_line("C:\\Users\\12280\\Desktop\\进程.txt");
    int size=3*n;
    FILE *fp=fopen("C:\\Users\\12280\\Desktop\\res.txt","a");
    printf("进程名 到达时间 运行时间 开始时间 结束时间 周转时间  带权周转时间\n");
    for(i=0; i<3*n; i+=3)
    {
        pcbs[i].WholeTime=pcbs[i].FinishTime-pcbs[i].StartTime;
        pcbs[i].WeightWholeTime=pcbs[i].WholeTime/pcbs[i].ServiceTime;
        x+=pcbs[i].WholeTime;
        y+=pcbs[i].WeightWholeTime;
        printf("%4d  %6d  %6d  %6d  %6d  %8.1f  %10.1f\n",pcbs[i].name,pcbs[i].ArriveTime,pcbs[i].ServiceTime,pcbs[i].StartTime,pcbs[i].FinishTime,pcbs[i].WholeTime,pcbs[i].WeightWholeTime);
        fprintf(fp,"进程名字=%4d  进程到达时间=%6d  进程服务时间=%6d  进程开始时间=%6d  进程结束时间=%6d  周转时间=%8.1f  带权周转时间=%10.1f\n",pcbs[i].name,pcbs[i].ArriveTime,pcbs[i].ServiceTime,pcbs[i].StartTime,pcbs[i].FinishTime,pcbs[i].WholeTime,pcbs[i].WeightWholeTime);
    }
    averageWholeTime=x/n;
    averageWeightWhole=y/n;
    printf("平均周转时间=%.2f  平均带权周转时间=%.2f\n",averageWholeTime,averageWeightWhole);
    fprintf(fp,"平均周转时间=%.2f  平均带权周转时间=%.2f\n",averageWholeTime,averageWeightWhole);
    fclose(fp);
    return 0;
}
void run_FCFS() //运行未完成的进程
{
    int n=count_line("C:\\Users\\12280\\Desktop\\进程.txt");
    int size=3*n;
     FILE *fp=fopen("C:\\Users\\12280\\Desktop\\res.txt","a");
    for(i=0;i<size;i+=3){
        time = pcbs[i].ArriveTime>time?pcbs[i].ArriveTime:time;
        pcbs[i].StartTime=time;
        printf("--->时刻:%d,  正在运行的作业:%d\n",time,pcbs[i].name);
        time+=pcbs[i].ServiceTime;
        pcbs[i].runFlag=1;
        pcbs[i].FinishTime=time;
        pcbs[i].WholeTime=pcbs[i].FinishTime-pcbs[i].ArriveTime;
        pcbs[i].WeightWholeTime=pcbs[i].WholeTime/pcbs[i].ServiceTime;
        x+=pcbs[i].WholeTime;
        y+=pcbs[i].WeightWholeTime;
        // printf("\n===========================================================================\n");
        printf("作业名   到达时间  开始时间    服务时间  完成时间   周转时间   带权周转时间\n");
        // printf("---------------------------------------------------------------------------\n");
        printf("%4d  %6d  %10d  %10d  %8d  %10.1f  %10.2f\n",pcbs[i].name,pcbs[i].ArriveTime,pcbs[i].StartTime,pcbs[i].ServiceTime,pcbs[i].FinishTime,pcbs[i].WholeTime,pcbs[i].WeightWholeTime);
        fprintf(fp,"进程名字=%4d  进程到达时间=%6d  进程开始时间=%10d  进程服务时间=%10d  进程结束时间=%8d  周转时间=%10.1f  带权周转时间=%10.2f\n",pcbs[i].name,pcbs[i].ArriveTime,pcbs[i].StartTime,pcbs[i].ServiceTime,pcbs[i].FinishTime,pcbs[i].WholeTime,pcbs[i].WeightWholeTime);
    }
    averageWholeTime=x/n;
    averageWeightWhole=y/n;
    printf("平均周转时间=%.2f  平均带权周转时间=%.2f\n",averageWholeTime,averageWeightWhole);
    fprintf(fp,"平均周转时间=%.2f  平均带权周转时间=%.2f\n",averageWholeTime,averageWeightWhole);
    fclose(fp);
}
void getInfo()          //获得进程信息并创建进程
{
    char* path="C:\\Users\\12280\\Desktop\\进程.txt";//读取文件里的信息
    int data[100],i;
    int n=count_line("C:\\Users\\12280\\Desktop\\进程.txt");
    int size=3*n;
    FILE *fp=fopen(path,"r");
    for(i=0;!feof(fp);i++){
        fscanf(fp,"%d",&data[i]);
    }
    for(i=0;i<size;i+=3)
    {
        pcbs[i].name=data[i];
        pcbs[i].ArriveTime=data[i+1];
        pcbs[i].ServiceTime=data[i+2];
        pcbs[i].serviceTime1=data[i+2];
    }
    for(i=0;i<size;i+=3){
        pcbs[i].StartTime=0;
        pcbs[i].FinishTime=0;
        pcbs[i].WholeTime=0;
        pcbs[i].WeightWholeTime=0;
        pcbs[i].runFlag=0;
        pcbs[i].startFlag=0;
    }
}
void main()
{   
    int k;
    FILE *fp=fopen("C:\\Users\\12280\\Desktop\\res.txt","a");
    printf("选择要进行调度的算法 1:先来先服务算法模拟;2:时间片轮转算法模拟\n");
    scanf("%d",&k);
    switch (k)
    {
    case 1:
        printf("先来先服务算法模拟\n");
        getInfo();
        run_FCFS();
        main();
        break;
    case 2:
        printf("时间片轮转算法模拟\n");
        getInfo();
        run_RR();
        poutput();
        main();
    default:
        break;
    }
}

 

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值