
本实验可采用优先数调度算法或时间片轮转算法或两者相结合进行模拟程序的设计。
一、预备知识
- 进程管理。
- 优先数调度算法、时间片轮转算法。
二、目的
1.加深对进程、进程控制块及进程队列等概念的理解。
2.了解优先数和时间片轮转调度算法的具体实施办法,加深对进程管理各部分内容的理解。
三.要求
1.掌握进程管理中主要数据结构的设计。
2.熟悉进程调度算法、进程控制机构、同步机构、通讯机构的实施。
四、实验内容
进程调度模拟程序的设计,包括以下2种调度算法:采用优先数调度算法的模拟进程调度程序、采用时间片轮转调度算法的模拟进程调度程序。
要求如下:
(1)设计进程控制块PCB表结构,分别适用于优先权调度算法和时间片轮转调度算法。
PCB结构包括以下信息:进程名、进程优先数(或轮转时间片),进程所占用的CPU时间,进程的状态,当前队列指针等。根据调度算法的不同,PCB结构的内容可以作适当的增删。
(2)建立进程就绪队列。对两种不同算法编制入链子程序。
(3)设计的程序中能显示或打印进程控制块的动态变化过程。
五、思路
该进程调度我运用了c++来编写,用数组的方式存储和更改进程情况,本次实验主要实现俩个算法。我根据自己的理解进行解释
先来先服务算法:
按照作业到达的先后次序来进行调度,先到的作业可以先执行,后到的则放入就绪队列中。
时间片轮转算法:
先定义好时间片轮转的周期,假如周期为1,则每个作业执行1秒后看就绪是否有作业在等候,若有,则让出cpu位置,而当前的作业则进入就绪队列中,不断地循环,直至作业全部完成。
其中还包括了俩个重要的时间
周转时间
周转时间 = 完成时间 - 到达时间
带权周转时间
带权周转时间 = 周转时间 / 运行时间
先来先服务算法和时间片轮转算法的思路为:主要运用了队列的结构来完成,用while语句,内涵多个if——else语句来执行。为了更方便的理解,我已在下面的代码中做了注释。
六、代码
#include
#include
#include
#include
using namespace std;
struct PCB
{
string name; //进程名称
int daodat; //进程到达的时间
int fuwut; //服务的时间
int zhongzhit; //终止的时间
int wait_time; //等待的时间
double quan; //带权时间
bool ifrun; //用来辨认真假
int RR_time; //时间片完
} pcb[20];
queue
PCB Que[1000];//就绪队列
PCB fcfs[30]; //先来先服务
PCB rr[20]; //时间片轮转
int top = 0;
void menu() //菜单显示
{
cout << "进程调度" << endl;
cout << "1. 请输入你的进程" << endl;
cout << "2. 显示进程" << endl;
cout << "3. 先来先服务算法" << endl;
cout << "4. 时间片轮转算法" << endl;
cout << "5. 算法结果对比" << endl;
cout << "0. 退出" << endl;
}
void init()//进程的情况
{
pcb[0] = {"a", 1, 5, 0, 0, 0, false, 0};
pcb[1] = {"b", 2, 1, 0, 0, 0, false, 0};
pcb[2] = {"c", 3, 7, 0, 0, 0, false, 0};
pcb[3] = {"d", 4, 3, 0, 0, 0, false, 0};
pcb[4] = {"e", 5, 9, 0, 0, 0, false, 0};
pcb[5] = {"f", 6, 6, 0, 0, 0, false, 0};
}
void input() //输入进程的情况
{
for(int i = 0; i < 6; i++)
{
cout << "进程:" << i << endl;
cout << "请输入你的进程名字:" ;
cin >> pcb[i].name;
cout << "请输入你的进程到达时间:" ;
cin >> pcb[i].daodat;
cout << "请输入你的进程服务时间:" ;
cin >> pcb[i].fuwut ;
cout << endl;
}
}
void display() //展示作业情况
{
cout << "名称" ;
cout << " " ;
for(int i = 0; i <= 5; i++)
cout << pcb[i].name << " ";
cout << endl;
cout << "到达时间 " ;
for(int i = 0; i <= 5; i++)
cout << pcb[i].daodat << " ";
cout << endl;
cout << "服务时间 ";
for(int i = 0; i <= 5; i++)
cout << pcb[i].fuwut << " ";
cout << endl;
system("pause");
}
void output(PCB a[])// 输出到达时间,服务时间,完成时间,周转时间,带权周转时间
{
int sumzhou = 0;
double sumdai = 0;
cout << " 名称" << "\t" << "到达时间" << "\t" << "服务时间" << "\t" << "完成时间" << "\t" << "周转时间" << "\t" << "带权周转时间" << endl;
for(int i = 0; i <= 5; i++)
{
cout << a[i].name << "\t" ;
cout << a[i].daodat << "\t\t" << a[i].fuwut << "\t\t" << a[i].zhongzhit << "\t\t" << a[i].zhongzhit-a[i].daodat << "\t\t" << (a[i].zhongzhit*1.0-a[i].daodat)/a[i].fuwut*1.0 << endl;
}
for(int i = 0; i <= 5; i++)
{
sumzhou += a[i].zhongzhit - a[i].daodat;// 周转时间 = 作业完成时刻 - 作业到达时刻
sumdai += (a[i].zhongzhit*1.0 - a[i].daodat) / a[i].fuwut*1.0;//带权周转时间 = 周转时间/运行时间
}
cout <<"平均周转时间:" << sumzhou*1.0/6 << "平均带权周转时间:" << sumdai/6 ;
system("pause");
}
void outputQue(int front,int rear) //就绪队列的进程
{
cout << "\t" << "当前就绪队列: " << endl;
for(int i = front; i < rear; i++)
{
cout << Que[i].name;
}
cout << endl;
}
void outsum()//算法的对比
{
cout << "先来先服务:" << endl;
output(fcfs);
cout << "时间片轮转:" << endl;
output(rr);
}
void FCFS()//先来先服务
{
top = 0;
PCB p= {"0",0,0,0};//初始化p
int now = 0;
int flag = 0; //0空闲 1运行
int r = 0;
while(1)
{
if(flag == 0 && p.name != "0")//若当前空闲,且不是第一次空闲,说明有进程执行完毕
{
cout << now << " " << p.name << "执行完毕" << endl;
p.ifrun = true; //赋值为真
fcfs[top++] = p;//将p的值写入fcfs数组里
}
if(top == 6)//如果进程全部执行完
break;
for(int i = r; i < 6; i++)//查看这一秒是否有进程到达
{
if(pcb[i].daodat == now) //说明此时间有进程到达
{
q.push(pcb[i]); //入队
cout << now << " " << pcb[i].name << "到达" << endl;
r = i + 1;//下一个进程
}
}
if(flag == 0 && !q.empty()) //空闲
{
p = q.front();//取队头执行
q.pop();//出队
cout << now << " " << p.name << "开始执行" << endl;
p.zhongzhit = p.fuwut + now; //服务时间加上当前时间则为终止的时间
flag = p.fuwut; //让服务的时间赋值给flag
}
now++;//下一秒的执行
if(flag > 0)
flag--;
Sleep(100);//程序睡眠100毫秒
}
output(fcfs);//输出结果
}
void RR()//时间片轮
{
int t = 0;
top = 0;
int front = 0;
int rear = 0;
PCB p= {"0",0,0,0};
int now = 0;
int flag = 0; //0空闲 1运行
int r = 0;
int time;
printf("请输入时间片间隔:");
scanf("%d",&time);
while(1)
{
if(t == time)//时间片用完
t = 0;
//扫描入队
for(int i = r; i < 6; i++)
{
if(pcb[i].daodat == now) //有进程到达
{
cout << now << " " << pcb[i].name << "到达" << endl;
Que[rear++] = pcb[i]; //入队
outputQue(front,rear);//输出就绪队列
r = i + 1;
}
}
if(p.name != "0") //不是第一次
{
if(p.RR_time >= p.fuwut) //如果已经完成服务
{
cout << now << " " << p.name << " " << "结束!" << endl;
p.zhongzhit = now;
t = 0;
rr[top++] = p;
if(top == 6)
break;
p.name = "0";
}
else if(t == 0) //如果没有完成并且时间片用完了
{
cout << now << " " << p.name << " " << "时间片用完!" << endl;
Que[rear++] = p;//p进队
outputQue(front,rear);
}
}
if(t == 0 && front != rear)
{
p = Que[front++];
cout << now << " " << p.name << "开始执行" << endl;
outputQue(front,rear);
}
now++;
t++;
p.RR_time++;
Sleep(100);//线程睡眠100毫秒
}
output(rr);
}
bool cmpSJF(PCB A,PCB B)
{
return A.daodat < B.daodat; //比较到达时间
}
bool cmpHRRN(PCB A,PCB B)
{
return A.quan > B.quan; //带权周转时间比较
}
int main()
{
int n;
init();
while(1)
{
menu();
scanf("%d",&n);
switch(n)
{
case 1:
input();
break;
case 2:
display();
break;
case 3:
FCFS();
break;
case 4:
RR();
break;
case 5:
outsum();
break;
case 0:
exit(1);
break;
default :
printf("请重新输入有效选项!\n");
}
}
}
六、运行的结果
也可输入自己想要的进程
七、结论
本次实验能让我更加理解进程调度的过程,完全明白并清晰了先来先服务和时间片轮转算法的核心,对进程在cpu,就绪队列等的状态执行也有了清晰的认识,在做本次实验过程中,我对于代码的学习也有了一定的认知,也应该多去学习别人的思想,不懂的多请教舍友,或者对这方面有了解的同学,这样才能够不断地进步。
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)