处理机调度算法
一.需求分析
基本要求:通过先来先服务算法和时间片轮转法实现处理机调度
二.算法分析
- 先来先服务算法:先进来的进程,先被处理机调度运行。即先输入的进程,放在就绪队列的对头,然后处理机每次对就绪队列头的进程进行调度。
- 时间片轮转算法:每次从对就绪队列头的进程调度,然后在一个时间片内进行运行,若在一个时间片内运行完,则把该进程信息输出;若不能在一个时间片运行完,就把该进程放在就绪队列的尾。
三.实验设计
-
设计步骤:
1.先创建一个进程,对该进程分配资源信息
2.若资源分配成功,就把该进程放在就绪队列的队尾;若资源分配不成功, 则把该进程放在阻塞队列的队尾。
3.通过动态计算时间片,通过计算就绪队列中的进程运行时间的平均时间作为处理机调度的时间片。
4.使用先来先服务算法,对就绪队列的中进程按照进来的时间从小到大进行排序。
5.使用时间片算法对进程进行调度,先对就绪队列进程调度,对运行完的进程释放所申请的资源,然后在阻塞队列中进行判断,若系统的资源可供阻塞队列中阻塞进程,则对阻塞进程进行分配资源,否则不进行资源分配(避免死锁);
6.输出调度顺序信息。 -
进程创建图:
-
进程调度图:
-
进程信息:
typedef struct pro{
int id;
int com_time;//进来时间
int time;//运行时间
int equ_tag;//外设,equ_tag为1,表示IO;equ_tag为2,表示printer
int num;//外设个数
pro *next;
}pro,*process; -
就绪队列:
process L;
使用单向不循环静态链表存放就绪进程,运行完的进程在就绪队列中进行删除,释放外设资源,未运行完的进程放在就绪队列的尾。 -
阻塞队列:
Process wait;
使用单向不循环静态链表存放就绪进程,未申请到外设资源的进程放入到阻塞队列中,在一个进程运行完之后,释放出自己的外设资源,然后给阻塞队列中的进程申请外设资源,若申请成功,则加入到就绪队列的尾。 -
调度顺序:
输出处理机的调度顺序,以及每个进程的进程信息。
四.代码实现
#include<iostream>
#include<malloc.h>
#include<windows.h>
#include<string>
#define MAX 10
//#define IO 4
//#define Printer 3
using namespace std;
typedef struct pro{
int id;
int com_time;//进来时间
int time;//运行时间
int equ_tag;//外设,equ_tag为1,表示IO;equ_tag为2,表示printer
int num;//外设个数
pro *next;
}pro,*process;
process head;//指向头
process tail;//指向尾
int count_IO;//动态输入外设个数
int count_Printer;
process L,R,SL,RL,wait,P_L,P_wait;
int show_time;
void Create(process &L,int n,process &wait);
int Compute(process L);//动态计算时间片的大小
void Apply(process &L);
void Run(process &L,process &R,process &wait);
void Output(process R);
//辅助函数
void Delete(process &L,int id);
void Sort(process &L,process &SL);//按照进来时间进行排序(com_time越小,排在队列前面)
void Reverse(process &L,process &RL);//倒序插入后的转置 、
void menu();
int main(){
menu();
}
void Apply(process &L){
cout<<"请输入该系统IO个数,Printer个数"<<endl;
cin>>count_IO>>count_Printer;
cout<<"请输入要创建的进程的个数"<<endl;
int n;
cin>>n;
if(n>MAX){
cout<<"内存已满"<<endl;
system("pause");
system("cls");
menu();
}
else{
Create(L,n,wait);
}
}
void Create(process &L,int n,process &wait){//倒序创建
process it,q;
L=(process)malloc(sizeof(pro));
L->next=NULL;
wait=(process)malloc(sizeof(pro));
wait->next=NULL;
head=L->next;
tail=head;
for(int i=0;i<n;i++){
process p=(process)malloc(sizeof(pro));
cout<<"请输入进程信息:进程标识,进来时间,运行时间,外设名称,外设个数"<<endl;
cin>>p->id>>p->com_time>>p->time>>p->equ_tag>>p->num;
if(p->equ_tag==1){
count_IO=count_IO-p->num;//外设够,给进程分配
if(count_IO>=0){//外设够,放入就绪队列
p->next=L->next;
L->next=p;
}
else
{
count_IO=count_IO+p->num;//外设不够,一个都不给进程,避免死锁
q=(process)malloc(sizeof(pro));
q->id=p->id;
q->com_time=p->com_time;
q->time=p->time;
q->equ_tag=p->equ_tag;
q->num=p->num;
q->next=wait->next;
wait->next=q;
}
}
if(p->equ_tag==2){
count_Printer=count_Printer-p->num;
if(count_Printer>=0){//外设够,放入就绪队列
p->next=L->next;
L->next=p;
}
else{
count_Printer=count_Printer+p->num;
q=(process)malloc(sizeof(pro));
q->id=p->id;
q->com_time=p->com_time;
q->time=p->time;
q->equ_tag=p->equ_tag;
q->num=p->num;
q->next=wait->next;
wait->next=q;
}
}
}
}
int Compute(process L){//动态计算时间片
int sum,time,total;//total为进程总数,time为时间片算法中的时间
sum=0;
total=0;
process it;
it=L->next;
while(it){
sum+=it->time;
total++;
it=it->next;
}
time=(int)sum/total+1;
return time;
}
//运行完在L中进行删除该进程,并在R中加入该进程
void Run(process &L,process &R,process &wait){
int count=0;
int time=Compute(L);
R=(process)malloc(sizeof(pro));
R->next=NULL;
while(1){
process it,it_w;
it=L->next;
it_w=wait->next;
if(it!=NULL){//L已经没有待运行的进程
while(it){
if(it!=NULL){
int p_id=it->id;
int p_time=it->time;
int p_com_time=it->com_time;
int p_equ_tag=it->equ_tag;
int p_num=it->num;
if(p_time>time){//一个时间片运行不完,放入就绪队列的队尾
p_time=time;
process s;
s=(process)malloc(sizeof(pro));
s->id=it->id;
s->com_time=it->com_time;
s->time=it->time-time;
s->equ_tag=it->equ_tag;
s->num=it->num;
if(tail==NULL){//只有一个元素的时候
tail=L;
}
s->next=tail->next;
tail->next=s;
tail=tail->next;//尾指针后移
Delete(L,p_id);
}
process p;
p=it;
p=(process)malloc(sizeof(pro));
p->id=p_id;
p->com_time=p_com_time;
p->equ_tag=p_equ_tag;
p->num=p_num;
p->time=p_time;
//运行时进行插入,若已运行完,在L中进行删除
p->next=R->next;
R->next=p;
it->time=it->time-time;
if(it->time<=0){//一个时间片富余
if(p->equ_tag==1){
count_IO=count_IO+p_num;
while(it_w){
if(it_w->num<=count_IO){
process t;
t=(process)malloc(sizeof(pro));
t->id=it_w->id;
t->com_time=it_w->com_time;
t->time=it_w->time;
t->equ_tag=it_w->equ_tag;
t->num=it_w->num;
t->next=tail->next;
tail->next=t;
tail=tail->next;//尾指针后移
count_IO-=it_w->num;
Delete(wait,t->id);
it_w=it_w->next;
}
else{
it_w=it_w->next;
}
}
}
if(p->equ_tag==2){
count_Printer+=p_num;
while(it_w){
if(it_w->num<=count_Printer){
process t;
t=(process)malloc(sizeof(pro));
t->id=it_w->id;
t->com_time=it_w->com_time;
t->time=it_w->time;
t->equ_tag=it_w->equ_tag;
t->num=it_w->num;
t->next=tail->next;
tail->next=t;
tail=tail->next;//尾指针后移
count_Printer-=it_w->num;
Delete(wait,t->id);
it_w=it_w->next;
}
else{
it_w=it_w->next;
}
}
}
Delete(L,p_id);
}
it=it->next;
}
else//L中已经没有待运行的进程
{
break;
}
}
}
else
{
break;
}
}
}
void Output(process R){
process it;
it=R->next;
cout<<"处理机调度顺序为:"<<endl;
cout<<"进程标号 进来时间 运行时间 外备名称 外备个数"<<endl;
while(it){
cout<<" "<<it->id<<" "<<it->com_time<<" "<<it->time<<" "<<it->equ_tag<<" "<<it->num<<endl;
it=it->next;
}
}
void Delete(process &L,int id){
process p,q;
p=L;
while(p->next){
q=p->next;
if(q->id==id){
p->next=q->next;
break;
}
p=p->next;
}
}
void Sort(process &L,process &SL){//先进先服务
SL=(process)malloc(sizeof(pro));
SL->next=NULL;
process it,it1;
it=L->next;
int max_time;//com_time最小不能为0,倒序插入法,所以选最大时间
int id,time,com_time,equ_tag,num;
while(it){
max_time=it->com_time;
id=it->id;
com_time=it->com_time;
time=it->time;
equ_tag=it->equ_tag;
num=it->num;
it1=L->next->next;
if(L->next->next!=NULL)
{
while(it1){
if(it1->com_time>max_time){//大于max_time交换,否则不交换直接赋值
max_time=it1->com_time;
com_time=it1->com_time;
id=it1->id;
time=it1->time;
equ_tag=it1->equ_tag;
num=it1->num;
it1=it1->next;
}
else{
it1=it1->next;
}
}
}
//否则表示就绪队列中只有一个进程,不需要比较
process p;
p=(process)malloc(sizeof(pro));
p->id=id;
p->com_time=com_time;
p->time=time;
p->equ_tag=equ_tag;
p->num=num;
p->next=SL->next;
SL->next=p;
Delete(L,id);
it=L->next;
//it=it->next;
}
it=SL->next;
while(it){//重新定位尾指针
tail=it;
it=it->next;
}
}
void Reverse(process &R,process &RL){//将R转换为RL,为输出准备
RL=(process)malloc(sizeof(pro));
process it=R->next;
RL->next=NULL;
//process it1=RL->next;
process p;
int id,time,com_time;
while(it){
p=(process)malloc(sizeof(pro));
p->id=it->id;
p->com_time=it->com_time;
p->time=it->time;
p->equ_tag=it->equ_tag;
p->num=it->num;
p->next=RL->next;
RL->next=p;
it=it->next;
}
}
void menu(){
cout<<"\t\t\t"<<"请选择您要进行的操作"<<endl;
cout<<"\t\t\t"<<"退出运行------------0"<<endl;
cout<<"\t\t\t"<<"创建进程------------1"<<endl;
cout<<"\t\t\t"<<"查看时间片----------2"<<endl;
cout<<"\t\t\t"<<"查看就绪队列--------3"<<endl;
cout<<"\t\t\t"<<"查看阻塞队列--------4"<<endl;
cout<<"\t\t\t"<<"查看调度顺序--------5"<<endl;
int choose;
while(1){
cout<<"请您输入操作编号"<<endl;
cin>>choose;
switch (choose){
case 0:
exit(1);
break;
case 1:
Apply(L);
show_time=Compute(L);
Sort(L,SL);
system("pause");
system("cls");
menu();
break;
case 2:
cout<<"时间片为:"<<show_time<<endl;
system("pause");
system("cls");
menu();
break;
case 3:
Output(SL);
system("pause");
system("cls");
menu();
break;
case 4:
Output(wait);
system("pause");
system("cls");
menu();
break;
case 5:
Run(SL,R,wait);
Reverse(R,RL);
Output(RL);
system("pause");
system("cls");
menu();
break;
default:
cout<<"请输入正确的编号!"<<endl;
}
}
}
五.测试结果
- IO,Printer充足情况:
- 主界面
- 创建进程
-
时间片(按照初始就绪队列中进程计算时间片)
-
就绪队列
-
阻塞队列(IO,Printer外设都充足,所以阻塞队列中为空。)
-
调度结果( 外设充足,此时相当于先来先服务调度,即按照进来时间进行调度)
-
IO,Printer不足情况:
-
主界面
-
创建进程
-
时间片(按照初始就绪队列中进程计算时间片)
-
就绪队列
-
阻塞队列
-
调度顺序