实验一、处理器调度
【实习目的】
在采用多道程序设计的系统中,往往有若干个进程同时处于就绪状态。当就绪进程个数大于处理器数时,就必须依照某种策略来决定哪些进程优先占用处理器。本实习模拟在单处理器情况下的处理器调度,帮助学生加深了解处理器调度的工作。
【实习内容】
选择一个调度算法,实现处理器调度
【实习题目】
设计一个按时间片轮转法实现处理器调度的程序。
[要求]:
(1) 假定系统有五个进程,每个进程用一个进程控制块PCB来代表。进程控制块的格式为:
l 进程名——作为进程的标识。
l 指针——进程按顺序排成循环队列,用指针指出下一个进程的进程控制块的首地址,最后一个进程的指针指出第一个进程的进程控制块首地址。
l 要求运行时间——假设进程需要运行的单位时间数。
l 已运行时间——假设进程已经运行的单位时间数,初始值为“0”。
l 状态——有两种状态,“就绪”和“结束”,初始状态都为“就绪”,用“R”表示。当一个进程运行结束后,它的状态为“结束”,用“E”表示。
(2)本实习是模拟处理器调度的功能,所以,对被选中的进程并不实际的启动运行,而是执行:已运行时间+1来模拟进程的一次运行,表示进程已经运行过一个单位的时间。
(3) 在所设计的程序中应有显示或打印语句,能显示或打印每次选中进程的进程名以及运行一次后进程队列的变化。
【程序中使用的数据结构及符号说明】
1. 进程控制块PCB的结构
typedef struct node
{
char name[2]; //进程名
int roundtime; //轮转时间片
int runnedtime; //已运行时间
int needtime; //还需运行时间
int count; //计数器
char state; //进程状态
struct node *next; //链指针
}PCB;
2. 主要程序块
Void show();输出就绪队列的基本信息
Void insert();插入函数
PCB *del();删除节点
Void create();创建进程PCB
Void roundtime();时间片论算法函数
Void main();主函数
3. 特殊符号说明
定义以下几个结构体,令其内容初值为空。
PCB *ready=NULL; //队头指针(等待调用)
PCB *run=NULL; //记录正在运行的结点的指针
PCB *end=NULL; //记录已经运行完成的结点的指针
PCB *tail=NULL; //队尾指针
【流程图】
【源程序】
#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
#include<string.h>
typedef struct node
{
char name[2]; //进程名
int roundtime; //轮转时间片
int runnedtime; //已运行时间
int needtime; //还需运行时间
int count; //计数器
char state; //进程状态
struct node *next; //链指针
}PCB;
PCB *ready=NULL; //队头指针(等待调用)
PCB *run=NULL; //记录正在运行的结点的指针
PCB *end=NULL; //记录已经运行完成的结点的指针
PCB *tail=NULL; //队尾指针
int n;
/*输出就绪进程队列*/
void show()
{
PCB *p=ready; //p指向头指针
if(ready!=NULL)
printf("进程名 已运行时间 还需时间 计数器 时间片 状态\n");
while(p!=NULL)
{
printf(" %s %d %d %d %d %c\n",p->name,p->runnedtime,p->needtime, p->count,p->roundtime,p->state);
p=p->next;
}
}
/*插入函数*/
void insert(PCB *p)
{
if(tail!=NULL)
tail->next=p;
tail=p;
if(ready==NULL)
ready=p;
}
/*出队*/
PCB *del()
{
PCB *p=ready;
ready=ready->next;
if(ready==NULL)
tail=NULL;
p->next=NULL;
return p;
}
/*创建进程PCB*/
void create()
{
PCB *p;
int i,time;
char name[2];
printf("输入进程名和要求运行的时间:\n");
for(i=0;i<n;i++)
{
p=(PCB *)malloc(sizeof(PCB)); //创建新的空间
scanf("%s",name); //键盘输入进程名
scanf("%d",&time); //键盘输入要运行时间
strcpy(p->name,name);
p->runnedtime=0; //已运行时间开始为0
p->needtime=time; //还需要的时间为总时间
p->count=0; //计数器初值为0
p->state='R'; //进程初始状态为ready
p->roundtime=1; //时间片论时间为1
p->next=NULL; //预处理结点与队列断开,若没有运行完成,则插入到队尾;否则就视为删除
insert(p);
}
printf("\n\n\n");
printf("**************************************************\n");
printf(" 进程信息 \n");
printf("**************************************************\n");
show();
}
/*时间片轮转法算法*/
void roundtime()
{
PCB *tial=NULL;
int k=1; //记录运行次数
while(ready!=NULL)
{
run=del();
run->runnedtime=run->runnedtime+1;
run->needtime=run->needtime-1;
run->count=run->count+1;
if(run->needtime==0) /*运行完时将其变为完成态,插入完成队列*/
{
printf("\n\n\n********第%d次运行结果*******\n",k);printf("进程%s已完成!\n",run->name);
end=run;
end->state='E';
}
else
if(run->count==run->roundtime) /*如果时间片到*/
{
printf("\n********第%d次运行结果*******\n",k);
run->count=0; /*记数器置零*/
run->state='R';/*将进程插入到就绪队列中等待轮转*/
insert(run);
}
k++;
show();
}
}
void main()
{
printf("\n\n");
printf(" ******************************\n");
printf(" **时间片轮转法实现处理器调度**\n");
printf(" ******************************\n\n\n\n");
printf("输入创建进程数目:");
scanf("%d",&n);
create();
roundtime();
}
【运行结果】
【结束语】
通过本次实验,我对时间片轮转的调度思想有了进一步的了解,通过动手实现其调度算法,更加深刻的理解了时间片轮转调度算法与其他几种算法的不同和优点。同时,在实验过程中,回顾书本上的理论知识,巩固了我的知识。