进程调度算法思想以及模拟算法

本文详细介绍了先来先服务算法(FCFS)、短进程优先算法(SPF)、高优先级算法(HPF,包括非抢占式与抢占式)和时间片轮转算法(RR)。通过实例展示了这些调度算法的工作原理、执行顺序以及它们在平均周转时间上的表现。
摘要由CSDN通过智能技术生成

先来先服务算法(FCFS)

​ 用于进程调度时,每次调度从就绪队列中选择一个最先进入该队列的进程,为之分配处理机,投入运行。属于非抢占式算法。

进程名到达时间(arrive)服务时间(service)开始时间(start)完成时间(finsh)周转时间(time)
A03033
B26397
C449139
D65131812
E82182012
执行顺序A B C D E平均周转时间8.6

算法思想:使用finsh1记录当前时间。如果arrive小于finsh1则进程finsh为finsh1+service,否则finsh1 = arrive, finsh = finsh1+arrive

bool cmp_time(PCB a,PCB b){
    return a.arrive < b.arrive;
}
void FCFS(){  //谁来就执行谁,没难度
    sort(pcb,pcb+n,cmp_time);
    pcb[0].start = pcb[0].arrive;
    pcb[0].time = pcb[0].service;
    int finsh = pcb[0].start + pcb[0].service;
    list.push(pcb[0].name);
    for(int i = 1; i < n; i++){
    	pcb[i].start = max(pcb[i-1].start+pcb[i-1].service,pcb[i].arrive);
        pcb[i].finsh = finsh+pcb[i].service;
        finsh = pcb[i].finsh;
        pcb[i].time =  pcb[i].start + pcb[i].service - pcb[i].arrive;
        //start = max(pcb[i+1].arrive,start+pcb[i].service);
        //pcb[i+1].start = start;
        pcb[i].state = 'f';
        list.push(pcb[i].name);
        //finsh[i] = pcb[i];
    }
    show();
}

短进程优先算法(SPF)

​ 每次选取需要服务时间最短的进程来调用,直到进程完成才执行下一个进程。

进程名到达时间(arrive)服务时间(service)开始时间(start)完成时间(finsh)周转时间(time)
A03033
B26397
C44111511
D65152014
E829113
执行顺序A B E C D平均周转时间7.6

算法思想:将进程按照service排序。在while(1)循环中:如果finsh1 > arrive 并且进程状态为wait状态那么执行该进程 finsh = finsh1 + arrive,状态改为完成状态,否则执行下一个进程,如果所有进程都没有到达finsh那么finsh自增。直到完成状态的进程数为n那么退出循环。

bool cmp_service_time(PCB a, PCB b){
    if(a.arrive != b.arrive)
        return a.service < b.service;
    else return a.arrive < b.arrive;
}
void SPF(){
    int wstate = 1;                 //进程完成的个数
	sort(pcb,pcb+n,cmp_time);       //首先按照到达时间排序,找到最先执行的作业
    pcb[0].start = pcb[0].arrive;   //开始时间即为到达时间,PS:不限制开始时间
    pcb[0].time = pcb[0].service;
    pcb[0].state = 'f';
    int finsh = pcb[0].start + pcb[0].service;
    list.push(pcb[0].name);             
    sort(pcb+1,pcb+n,cmp_service_time);         
    //对进程按照需要的时间进行排序
    for(int i = 1; i< n*n && wstate < n;){      
//因为进程按照长短排序,因此当前进程不一定在当前时间到达。对进程进行循环扫描,找到在当前时间之前并且处于未完成状态的进程
        if(pcb[i%n].arrive < finsh && pcb[i%n].state == 'w'){
            pcb[i%n].start = finsh;
            pcb[i%n].time =  pcb[i%n].start + pcb[i%n].service - pcb[i%n].arrive;
            pcb[i%n].finsh =  pcb[i%n].start + pcb[i%n].service;
            pcb[i%n].state = 'f';
            finsh = finsh + pcb[i%n].service;
            wstate++;
            list.push(pcb[i%n].name);
        }
        i++;
    }
    show();
}

高优先级算法(HPF)

每次选取进程中优先级高的进程执行。高优先级算法分为抢占式和非抢占式两种:

{抢占式}:在进程执行过程中,如果有优先级比当前进程高的进程出现那么阻塞该进程执行优先级较高的进程,高优先级进程完成后才继续执行该进程

{非抢占式}:每次当前优先级执行完后再执行下一个优先级较高的进程

进程名到达时间(arrive)服务时间(service)优先级(priority)开始时间(start)完成时间(finsh)周转时间(time)
A032033
B261397
C444141814
D6559148
E823182012
执行顺序A B D C E平均周转时间8.8

算法思想:按照优先级排序,在while(1)循环中:如果finsh1 > arrive 并且进程状态为wait状态那么执行该进程 finsh = finsh1 + arrive,状态改为完成状态,否则执行下一个进程,如果所有进程都没有到达finsh那么finsh自增。直到完成状态的进程数为n那么退出循环。

bool cmp_priority(PCB a, PCB b){  // 数值越大优先权越大
    return a.priority > b.priority;
}
//非抢占式高优先级调度算法,思想类似于短作业调度算法
void HPF(){
    int wstate = 1;
	sort(pcb,pcb+n,cmp_time);
    pcb[0].start = pcb[0].arrive;
    pcb[0].time = pcb[0].service;
    pcb[0].state = 'f';
    int finsh = pcb[0].start + pcb[0].service;
    pcb[0].finsh = finsh;
    list.push(pcb[0].name);
    sort(pcb+1,pcb+n,cmp_priority);
    int pmin = pcb[1].arrive;
    for(int i = 1; i< n*n && wstate < n;){
        if(pcb[i%n].arrive < finsh && pcb[i%n].state == 'w'){
            pcb[i%n].start = finsh;
            pcb[i%n].time =  pcb[i%n].start + pcb[i%n].service - pcb[i%n].arrive;
            pcb[i%n].finsh =  pcb[i%n].start + pcb[i%n].service;
            pcb[i%n].state = 'f';
            finsh = finsh + pcb[i%n].service;
            wstate++;
            list.push(pcb[i%n].name);
        }
         i++;
    }
    show();

}

时间片轮转算法(RR)

​  轮转法是基于适中的抢占策略的,以一个周期性间隔产生时钟中断,当中断发生后,当前正在运行的进程被置于就绪队列中,然后基于先来先去服务策略选择下一个就绪作业的运行。这种技术也称为时间片,因为每个进程再被抢占之前都给定一片时间。时间片轮转算法只能是抢占式的

进程名到达时间(arrive)服务时间(service)优先级(priority)开始时间(start)完成时间(finsh)周转时间(time)
A032033
B26131816
C444141410
D65592115
E82318168
执行顺序AABCBDCEBDD平均周转时间10.4

算法思想:准备一个就绪队列,将没有完成的进程压入的进程队列队尾当中,每次取队头位置。

//时间片轮转
void RR(){
    int time = 0;
    int slice = 2; //设置时间片大小为2
    int i = 0;
    int num = 0;
    queue<PCB> q; //进程就绪队列
    sort(pcb,pcb+n,cmp_time);
    while(1){
        while(pcb[i].arrive <= time && pcb[i].state == 'w'){ //将所有在time时间以前并且在就绪状态的进程全部存入就绪队列并将状态改为运行态
            pcb[i].state = 'r';
            pcb[i].start = time;
            q.push(pcb[i]);
            i++;
        }
        PCB temp = q.front();  
        q.pop();
     if(temp.service > slice){ //如果所需时间大于时间片,那么将service减去时间片,再将进程转入就绪队列中
            temp.service = temp.service -slice;
            temp.state = 'r';
            q.push(temp);
            list.push(temp.name);
        }
        else if(temp.service  <= slice){    //如果所需时间小于等于时间片,那么完成时间为当前时间+所需时间,并将进程状态改为完成态。、
            pcb[temp.name -'A'].state == 'f';
            pcb[temp.name -'A'].finsh = time+temp.service;
            pcb[temp.name -'A'].time = pcb[temp.name -'A'].finsh - pcb[temp.name -'A'].arrive;
    		list.push(temp.name);
            
        }
        time = time + slice;     //时间按照时间片大小递增
        for(num = 0; num < n; num++){
            if(pcb[i].state =='w' || pcb[i].state == 'r') break;    //判断是否每一个进程状态都为完成态,如果都为完成态并且就绪队列中没有进程等待执行,那么退出循环
        }
        if(num == n && q.empty()) break;
    }
    show();
}
void show(){
    double sum1 = 0;
    double sum2 = 0;
      cout << "进程名\t进程到达时间\t进程要求服务时间\t进程开始时间\t进程完成时间\t周转时间\t带权周转时间" << endl;
      //cout << pcb[0].name <<"\t\t" << pcb[0].arrive << "\t\t" << pcb[0].service <<"\t\t" <<pcb[0].start<<"\t\t"<< pcb[0].start+pcb[0].service<<"\t\t"<<pcb[0].time <<"\n";
    for(int i = 0; i < n; i++){
       sum1 += pcb[i].time;
       sum2 += pcb[i].time*1.0/pcb[i].service;
       cout << pcb[i].name <<"\t\t" << pcb[i].arrive << "\t\t" << pcb[i].service <<"\t\t" <<pcb[i].start << "\t\t" <<pcb[i].finsh<<"\t\t"<<pcb[i].time<<"\t\t"<<pcb[i].time*1.0/pcb[i].service <<"\n";
    }
    cout << "平均周转时间:" << 1.0*sum1/n <<"\t" << "平均带权周转时间" << 1.0*sum2/n << endl; 
    cout <<"进程顺序:";
    while(!list.empty()){
    	 cout << list.front() << " ";
    	 list.pop();
	}
	cout << endl;
    cout <<"****************************************************************************************************************" << endl;
}

进程调度算法模拟。通过对进程调度算法模拟,进一步理解进程的基本概念,加深对进程运行状态和进程调度过程、调度算法的理解。 (1) 用C、C++、Java语言编程实现对5个进程采用动态优先权调度算法进行调度的过程。数据如下: 5个进程的到达时刻和服务时间见下表,忽略I/O以及其它开销时间,使用动态优先权算法进行调度,优先权初始值为100,请输出各个进程的完成时刻、周转时间、带权周转时间。 进程 到达时刻 服务时间 A 0 3 B 2 6 C 4 4 D 6 5 E 8 2 (2)每个用来标识进程进程控制块PCB可用结构来描述,包括以下字段(用不到的字段可以不定义)。  进程标识数ID。  进程优先数PRIORITY,并规定优先数越大的进程,其优先权越高。  进程已占用CPU时间CPUTIME。  进程还需占用的CPU时间ALLTIME。当进程运行完毕时,ALLTIME变为0。  进程的阻塞时间STARTBLOCK,表示当进程再运行STARTBLOCK个时间片后,进程将进入阻塞状态。  进程被阻塞的时间BLOCKTIME,表示已阻塞的进程再等待BLOCKTIME个时间片后,将转换成就绪状态。  进程状态STATE。  队列指针NEXT,用来将PCB排成队列。 (3)优先数改变的原则:  进程在就绪队列中呆一个时间片,优先数增加1。  进程每运行一个时间片,优先数减3。 (4)为了清楚地观察每个进程的调度过程,程序应将每个时间片内的进程的情况显示出来,包括正在运行的进程,处于就绪队列中的进程和处于阻塞队列中的进程。 (5)分析程序运行的结果,谈一下自己的认识。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

流云枫木

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值