先来先服务算法(FCFS)
用于进程调度时,每次调度从就绪队列中选择一个最先进入该队列的进程,为之分配处理机,投入运行。属于非抢占式算法。
进程名 | 到达时间(arrive) | 服务时间(service) | 开始时间(start) | 完成时间(finsh) | 周转时间(time) |
---|---|---|---|---|---|
A | 0 | 3 | 0 | 3 | 3 |
B | 2 | 6 | 3 | 9 | 7 |
C | 4 | 4 | 9 | 13 | 9 |
D | 6 | 5 | 13 | 18 | 12 |
E | 8 | 2 | 18 | 20 | 12 |
执行顺序 | 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) |
---|---|---|---|---|---|
A | 0 | 3 | 0 | 3 | 3 |
B | 2 | 6 | 3 | 9 | 7 |
C | 4 | 4 | 11 | 15 | 11 |
D | 6 | 5 | 15 | 20 | 14 |
E | 8 | 2 | 9 | 11 | 3 |
执行顺序 | 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) |
---|---|---|---|---|---|---|
A | 0 | 3 | 2 | 0 | 3 | 3 |
B | 2 | 6 | 1 | 3 | 9 | 7 |
C | 4 | 4 | 4 | 14 | 18 | 14 |
D | 6 | 5 | 5 | 9 | 14 | 8 |
E | 8 | 2 | 3 | 18 | 20 | 12 |
执行顺序 | 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) |
---|---|---|---|---|---|---|
A | 0 | 3 | 2 | 0 | 3 | 3 |
B | 2 | 6 | 1 | 3 | 18 | 16 |
C | 4 | 4 | 4 | 14 | 14 | 10 |
D | 6 | 5 | 5 | 9 | 21 | 15 |
E | 8 | 2 | 3 | 18 | 16 | 8 |
执行顺序 | 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;
}