按优先数调度算法实现处理机调度的程序 C++
(1)假定系统有五个进程,每一个进程用一个进程控制块PCB来代表。进程控制的格式为:
进程名
指针
要求运行时间
优先数
状态
其中,进程名——作为进程的标识,假设五个进程的进程名分别为P1,P2,P3,P4,P5。
指针——按优先数的大小把五个进程连成队列,用指针指出下一个进程的进程控制块的首地址,最后一个进程中的指针为“0”。
要求运行时间——假设进程需要运行的单位时间数。
优先数——赋予进程的优先数,调度时总是选取优先数大的进程先执行。
状态——可假设有两种状态,“就绪”状态和“结束”状态。五个进程的初始状态都为“就绪”,用“R”表示,当一个进程运行结束后,它的状态为“结束”,用“E”表示。
(2)在每次运行你所设计的处理机调度程序之前,为每个进程任意确定它的“优先数”和“要求运行时间”。
(3)为了调度方便,把五个进程按给定的优先数从大到小连成队列。用一单元指出队首进程,用指针指出队列的连接情况例:
队首标志
k2
P1 P2 P3 P4 P5 0 k4 k5 k3 k1 2 3 1 4 4 1 5 3 2 2 R R R R R PCB1 PCB2 PCB3 PCB4 PCB5
(4)处理机调度总是选队首进程运行。采用动态改变优先数的办法,进程每运行一次优先数就减“1”。由于本实验是模拟处理机调度,所以,对被选中的进程并不实际的启动运行,而是执行:“优先数-1 要求运行时间-1”来模拟进程的一次运行。
提醒注意的是:在实际的系统中,当一个进程被选中运行时,必须恢复进程的现场,让它占有处理机运行,直到出现等待事件或运行结束。在这里省去了这些工作。
- 进程运行一次后,若要求运行时间≠0,则再将它加入队列(按优先数大小插入,且置队首标志);若要求运行时间=0,则把它的状态修改成“结束”(E),且退出队列。
- 若“就绪”状态的进程队列不为空,则重复上面(4)和(5)的步骤,直到所有进程都成为“结束”状态。
- 在所设计的程序中应有显示或打印语句,能显示或打印每次被选中进程的进程名以及运行一次后进程队列的变化。
- 为五个进程任意确定一组“优先数”和“要求运行时间”,启动所设计的处理机调度程序,显示或打印逐次被选中进程的进程名以及进程控制块的动态变化过程。
源代码:
#include <iostream>
#include <iomanip>
using namespace std;
const int N=5;
//“进程”结构体
struct Process{
string p_name;
Process* p_next;
int time_needed;
int priority;
char status;
void set(string p_name, int time_needed, int priority, char status, Process* p_next = NULL){
this->p_name = p_name;
this->p_next = p_next;
this->time_needed = time_needed;
this->priority = priority;
this->status = status;
}
}p[N];
bool cmp_pri(Process a, Process b){
return a.priority > b.priority;
}
void mySwitch(Process &a, Process &b){
Process t=a;
a=b;
b=t;
}
void printAll(Process p[N]){
int i=0;
cout<<"Pname: ";
while(i!=5) cout<<setw(6)<<p[i++].p_name;
cout<<endl;
i=0;
cout<<"Pnext: ";
while(i!=5){
if(p[i].p_next!=NULL) cout<<setw(6)<<p[i++].p_next->p_name;
else{
cout<<setw(6)<<"NULL";
break;
}
}
cout<<endl;
i=0;
cout<<"Need: ";
while(i!=5) cout<<setw(6)<<p[i++].time_needed;
cout<<endl;
i=0;
cout<<"Prio: ";
while(i!=5) cout<<setw(6)<<p[i++].priority;
cout<<endl;
i=0;
cout<<"Status:";
while(i!=5) cout<<setw(6)<<p[i++].status;
cout<<endl;
while(1) if(getchar()=='\n') break;
}
int main(){
for(int i=0;i<N;i++){
string P = "P";
string t = P.append(to_string(i));
p[i].set(t, (i+1)*13%7, (i+1)*3%7, 'R'); //模仿“随机”生成一个进程表
//初始化链表
if(i!=4) p[i].p_next = &p[i+1];
else p[i].p_next = NULL;
}
cout<<"before sort:"<<endl;
printAll(p);
//按照优先权priority排序 只在初始化时进行一次
sort(p, p+N, cmp_pri);
//更新链表
for(int i=0;i<N;i++){
if(i!=4) p[i].p_next = &p[i+1];
else p[i].p_next = NULL;
}
cout<<"after sort(by priority):"<<endl;
int step=0;
while(1){
cout<<"step:"<<step++<<" prio:"<<p[0].p_name<<endl;
printAll(p);
//对头指针进行两个减减
if(p[0].status=='R'){
p[0].time_needed--;
p[0].priority--;
if(p[0].priority<0) p[0].priority=0; //要求priority不小于0
}
else break;
//如果头指针的time_needed == 0,则进行一次“向后插入”
if(p[0].time_needed==0 && p[0].status=='R'){
p[0].status='E';
for(int i=0;i<N-1;i++){
if(p[i+1].status=='R') mySwitch(p[i], p[i+1]);
else if(p[i+1].status=='E' && p[i+1].priority > p[i].priority) mySwitch(p[i], p[i+1]);
else break;
}
//更新链表顺序
for(int i=0;i<N;i++){
if(i!=4) p[i].p_next = &p[i+1];
else p[i].p_next = NULL;
}
}
//如果头指针的priority小于后一个的priority,则进行一次“向后插入”到准确的位置
if(p[0].priority < p[1].priority && p[1].status=='R'){
for(int i=0;i<N-1;i++){
if(p[i+1].priority > p[i].priority && p[i+1].status=='R') mySwitch(p[i], p[i+1]);
else break;
}
//更新链表顺序
for(int i=0;i<N;i++){
if(i!=4) p[i].p_next = &p[i+1];
else p[i].p_next = NULL;
}
}
}
}
结果记录:
今日杭州初雪❄️