一、实验目的要求
通过模拟进程控制方法和单处理机系统下的进程调度,了解进程的结构、进程的创建与撤销,进程的组织及进程的状态及其转换,掌握进程调度策略。
二、实验材料和仪器设备
Windows操作系统环境下的个人微机。
三、实验内容
实现对N(N的值不小于5)个进程采用动态优先权优先算法的进程调度。
注意:本实验为单机模拟进程调度算法,在程序设计时不需真正地建立线程或进程。
程序要求:为了清楚地观察诸进程的调度过程,程序中应有显示或打印语句,能显示或打印每次被选中进程的进程名,以及运行一次后进程队列的变化。打印程序运行时的初值和运行结果的要求如下:
I)各进程控制块的初始信息。
II)选中运行的进程名以及选中进程运行后的各进程控制块信息,且要求每选中一个进程运行后都要打印。
【提示】
(1)假定系统有5个进程,每一个进程用一个进程控制块PCB来代表,进程控制块的格式为:
进程名
需要运行时间
已用CPU时间
优先数
状态
其中,进程名——作为进程的标识,假设五个进程的进程名分别为P1,P2,P3,P4,P5。
需要运行时间——进程需要运行的单位时间数,以时间片为单位进行计算。
已用CPU时间——进程已经运行的单位时间数,初始值为0。
优先数——赋予进程的优先数,调度时总是选取优先数大的进程先执行。
状态——每个进程的状态可以是就绪 W(Wait)、运行R(Run)、完成F(Finish)三种状态之一。初始状态为“就绪”。
(2)处理机调度程序运行时,为每个进程任意确定它的“优先数”和“需要运行时间”; 可以事先人为地指定,也可以由随机数产生。
(3)处理机调度总是选队首进程运行。就绪进程获得 CPU后都只能运行一个时间片,用已占用CPU时间加1来表示。
(4)进程运行一个时间片后,如果进程已占用 CPU时间已达到所需要的运行时间,则撤消该进程;如果运行一个时间片后进程的已占用CPU时间还未达所需要的运行时间,也就是进程还需要继续运行,此时应将进程的优先数减1(即降低一级),然后把它插入就绪队列等待CPU。
由于本实验是模拟处理器调度,所以,对被选中的进程并不实际的启动运行,而是执行:“优先数-1;已用CPU时间+1;”来模拟进程的一次运行。
提醒注意的是:在实际的系统中,当一个进程被选中运行时,必须恢复进程的现场,让它占有处理器运行,直到出现等待事件或运行结束。在这里省去了这些工作。
(5)每进行一次调度程序都打印一次运行进程、就绪队列、以及各个进程的 PCB,以便进行检查。
重复以上过程,直到所要进程都完成为止。调度算法的流程图如下:
四、实验要求
1、根据给出的流程图认真编写程序,编译环境不限;
2、上机独立调试程序,验证代码的正确性。
五、源代码
#include<iostream>//引入输入输出函数
#include<queue>//引入队列
#include<vector>//引入容器
#include<string>
#define maxn 8//定义最多进程控制块
#define R true//运行态
#define F false//结束态
using namespace std;//使用标准命名空间
struct Node{
string name; //进程名
int *p; //指针
int ndtime; //需要运行时间
int prenum; //优先级数
int state; //状态
}pcb[maxn];//进程控制块
struct cmp{
bool operator()(const Node &p,const Node &q){
return p.prenum<q.prenum; //根据优先级数从大到小排序
}
};
void Init(){
//进程控制块初始化
printf("以下是进程数为5的情况的展示:\n");
pcb[1].name = "p1";//名称
pcb[1].ndtime = 6;//需要运行时间
pcb[1].prenum = 18;//优先级数
pcb[1].state = R;
pcb[2].name = "p2";
pcb[2].ndtime = 5;
pcb[2].prenum = 15;
pcb[2].state = R;
pcb[3].name = "p3";
pcb[3].ndtime = 8;
pcb[3].prenum = 19;
pcb[3].state = R;
pcb[4].name = "p4";
pcb[4].ndtime = 6;
pcb[4].prenum = 14;
pcb[4].state = R;
pcb[5].name = "p5";
pcb[5].ndtime = 10;
pcb[5].prenum = 16;
pcb[5].state = R;
}
void RunQueue(int n)
{
priority_queue<Node,vector<Node>,cmp> q;//优先队列<数据类型,容器类型(数组实现的容器),比较的方式>
vector<string> v;//创建一个vector容器,数据类型为string,动态数组名为v
for(int i=1;i<=n;++i){
//将五个进程加入队列
cout<<"将进程"<<pcb[i].name<<"加入队列"<<endl;
q.push(pcb[i]);
}
while(!q.empty()){
//非空一直循环
Node t = q.top();//让t等于当前队列顶部元素
q.pop();//移除块内第一个元素
cout<<"执行进程"<<t.name<<endl;
v.push_back(t.name);//尾部插入被执行的元素(即刚被执行的进程)
t.prenum -= 1;//被执行的进程优先级数-1
t.ndtime -= 1;//被执行的进程需要时间块-1
if(t.ndtime!=0){
//如果被执行的进程未运行完
q.push(t);//将进程t置于队列中
cout<<"将进程"<<t.name<<"再次加入队列"<<endl;
}
else{
//否则被执行的进程运行完,退出队列,状态设为结束
cout<<"进程"<<t.name<<"退出队列,状态为结束"<<endl;
t.state = F;
}
}
cout<<"============模拟进程结束============="<<endl;
cout<<"进程运行序列为:"<<endl;
for(int i=0;i<v.size();++i){
//vector容器的size()函数输出运行顺序
cout<<v[i]<<" ";
}
cout<<endl;
}
int main(){
Init();
RunQueue(5);
return 0;
}