实验项目一:单处理机系统的进程调度 4学时
(一)实验目的要求
通过模拟进程控制方法和单处理机系统下的进程调度,了解进程的结构、进程的创建与撤销,进程的组织及进程的状态及其转换,掌握进程调度策略。
(二)实验材料和仪器设备
Windows操作系统环境下的个人微机。
(三)实验内容
设计实现一个对N个进程采用动态优先权算法的进程调度。本实验为单机模拟进程调度算法,在程序设计时不需真正地建立线程或进程。
程序要求:为了清楚地观察诸进程的调度过程,程序中应有显示或打印语句,能显示或打印每次被选中进程的进程名,以及运行一次后进程队列的变化。打印程序运行时的初值和运行结果的要求如下:
I)进程控制块的初始状态。
II)选中运行的进程名以及选中进程运行后的各进程控制块状态。
对于II要求每选中一个进程运行后都要打印。
【提示】
(1)假定系统有5个进程,每一个进程用一个进程控制块PCB来代表,进程控制块的格式为:
进程名 |
指针 |
要求运行时间 |
优先数 |
状态 |
其中,进程名——作为进程的标识,假设五个进程的进程名分别为P1,P2,P3,P4,P5。
指针——按优先数的大小把5个进程连成队列,用指针指出下一个进程的进程控制块的首地址,最后一个进程中的指针为“0”。
要求运行时间——假设进程需要运行的单位时间数。
优先数——赋予进程的优先数,调度时总是选取优先数大的进程先执行。
状态——可假设有两种状态,“就绪”状态和“结束”状态。5个进程的初始状态都为“就绪”,用“R”表示,当一个进程运行结束后,它的状态为“结束”,用“E”表示。
(2)在每次运行设计的处理机调度程序之前,为每个进程任意确定它的“优先数”和“要求运行时间”。
(3)为了调度方便,把5个进程按给定的优先数从大到小连成队列。用一单元指出队首进程,用指针指出队列的连接情况。例:
队首标志
K2
K1 |
P1 |
K2 |
P2 |
K3 |
P3 |
K4 |
P4 |
K5 |
P5 |
|
0 |
|
K4 |
|
K5 |
|
K3 |
|
K1 |
|
2 |
|
3 |
|
1 |
|
2 |
|
4 |
|
1 |
|
5 |
|
3 |
|
4 |
|
2 |
|
R |
|
R |
|
R |
|
R |
|
R |
|
PCB1 |
|
PCB2 |
|
PCB3 |
|
PCB4 |
|
PCB5 |
(4)处理机调度总是选队首进程运行。优先权改变的原则,进程每运行一次优先数就减“1”。由于本实验是模拟处理器调度,所以,对被选中的进程并不实际的启动运行,而是执行:
优先数-1
要求运行时间-1
来模拟进程的一次运行。
提醒注意的是:在实际的系统中,当一个进程被选中运行时,必须恢复进程的现场,让它占有处理器运行,直到出现等待事件或运行结束。在这里省去了这些工作。
(5)进程运行一次后,若要求运行时间¹0,则再将它加入队列(按优先数大小插入,且置队首标志);若要求运行时间=0,则把它的状态修改成“结束”(E),且退出队列。
(6)若“就绪”状态的进程队列不为空,则重复上面(4)和(5)的步骤,直到所有进程都成为“结束”状态。
(7)为5个进程任意确定一组“优先数”和“要求运行时间”,启动所设计的处理机调度程序,显示或打印逐次被选中进程的进程名以及进程控制块的动态变化过程。
代码:
#include<iostream>
#include<queue>
#include<vector>
#define maxn 10
#define R true
#define E 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 RunQueue(int n);
void MuiltyInput();
void Init();
int main()
{
Init();
RunQueue(5);
MuiltyInput();
return 0;
}
void Init()
{
printf("以下是进程数为5的情况的展示:\n");
pcb[1].name = "k1";
pcb[1].ndtime = 10;
pcb[1].prenum = 17;
pcb[1].state = R;
pcb[2].name = "k2";
pcb[2].ndtime = 8;
pcb[2].prenum = 15;
pcb[2].state = R;
pcb[3].name = "k3";
pcb[3].ndtime = 9;
pcb[3].prenum = 16;
pcb[3].state = R;
pcb[4].name = "k4";
pcb[4].ndtime = 5;
pcb[4].prenum = 14;
pcb[4].state = R;
pcb[5].name = "k5";
pcb[5].ndtime = 6;
pcb[5].prenum = 18;
pcb[5].state = R;
}
void RunQueue(int n)
{
priority_queue<Node,vector<Node>,cmp> q;
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();
q.pop();
cout<<"执行进程"<<t.name<<endl;
v.push_back(t.name);
t.prenum -= 1;
t.ndtime -= 1;
if(t.ndtime!=0){
q.push(t);
cout<<"将进程"<<t.name<<"再次加入队列"<<endl;
}
else{
cout<<"进程"<<t.name<<"退出队列,状态为结束"<<endl;
t.state = E;
}
}
cout<<"============模拟进程结束============="<<endl;
cout<<"进程运行序列为:"<<endl;
for(int i=0;i<v.size();++i){
cout<<v[i]<<" ";
}
cout<<endl;
}
void MuiltyInput()
{
int n; //进程数
while(1){
printf("请输入进程数(1-6) : ");
scanf("%d",&n);
for(int i=1;i<=n;++i){
printf("请输入第%d个进程的 运行所需时间(5-10),优先级数(10-20),运行状态(0/1,初始为1):\n",i);
scanf("%d %d %d",&pcb[i].ndtime,&pcb[i].prenum,&pcb[i].state);
}
RunQueue(n);
}
}
运行结果截图:
假设5个进程的运行结果:
输入任意进程数的运行结果: