操作系统实验-设计一个按优先数调度算法实现处理器调度的程序

实验二
一、实验题目
设计一个按优先数调度算法实现处理器调度的程序
二、实验内容
(1) 假定系统有五个进程,每一个进程用一个进程控制块PCB来代表,进程控制块的格式为:
|进程名|
|指针|
|要求运行时间|
|优先数|
|状态|
其中,进程名——作为进程的标识,假设五个进程的进程名分别为P1,P2,P3,P4,P5。
指针——按优先数的大小把五个进程连成队列,用指针指出下一个进程的进程控制块的首地址,最后一个进程中的指针为“0”。
要求运行时间——假设进程需要运行的单位时间数。
优先数——赋予进程的优先数,调度时总是选取优先数大的进程先执行。
状态——可假设有两种状态,“就绪”状态和“结束”状态。五个进程的初始状态都为“就绪”,用“R”表示,当一个进程运行结束后,它的状态为“结束”,用“E”表示。
(2) 在每次运行你所设计的处理器调度程序之前,为每个进程任意确定它的“优先数”和“要求运行时间”。
(3) 为了调度方便,把五个进程按给定的优先数从大到小连成队列。用一单元指出队首进程,用指针指出队列的连接情况。例:
队首标志
操作系统实验-设计一个按优先数调度算法实现处理器调度的程序
(4) 处理器调度总是选队首进程运行。采用动态改变优先数的办法,进程每运行一次优先数就减“1”。由于本实验是模拟处理器调度,所以,对被选中的进程并不实际的启动运行,而是执行:
优先数-1
要求运行时间-1
来模拟进程的一次运行。
提醒注意的是:在实际的系统中,当一个进程被选中运行时,必须恢复进程的现场,让它占有处理器运行,直到出现等待事件或运行结束。在这里省去了这些工作。
(5) 进程运行一次后,若要求运行时间0,则再将它加入队列(按优先数大小插入,且置队首标志);若要求运行时间=0,则把它的状态修改成“结束”(E),且退出队列。
(6) 若“就绪”状态的进程队列不为空,则重复上面(4)和(5)的步骤,直到所有进程都成为“结束”状态。
(7) 在所设计的程序中应有显示或打印语句,能显示或打印每次被选中进程的进程名以及运行一次后进程队列的变化。
(8) 为五个进程任意确定一组“优先数”和“要求运行时间”,启动所设计的处理器调度程序,显示或打印逐次被选中进程的进程名以及进程控制块的动态变化过程。
三、实验过程
1、实验原理
(1) 假定系统有5个进程,每个进程用一个PCB来代表。PCB的格式为:
进程名、指针、要求运行时间、优先数、状态。
进程名——P1~P5。
指针——按优先数的大小把5个进程连成队列,用指针指出下一个进程PCB的首地址。 要求运行时间——假设进程需要运行的单位时间数。
优先数——赋予进程的优先数,调度时总是选取优先数大的进程先执行。
状态——假设两种状态,就绪,用R表示,和结束,用E表示。初始状态都为就绪状态。
(2) 每次运行之前,为每个进程任意确定它的“优先数”和“要求运行时间”。
(3) 处理器总是选队首进程运行。采用动态改变优先数的办法,进程每运行1次,优先数减1,要求运行时间减1。
(4) 进程运行一次后,若要求运行时间不等于0,则将它加入队列,否则,将状态改为“结束”,退出队列。
(5) 若就绪队列为空,结束,否则,重复(3)。
2、数据结构
操作系统实验-设计一个按优先数调度算法实现处理器调度的程序
进程控制块PCB:proName:进程名;runTime:运行时间;priorityNum:优先级;status:状态
优先队列readyQueue:就绪队列

3、算法设计
void tailCreate(PCB *L){
srand((unsigned int)time(0));
///以时间为随机数种子,保证每次随机数不一样
int priority = rand() % 5;///随机优先数
PCB *s, *r = L;
for (int i = 0; i<5; i++)
{ ///随机时间为1到50
int number = rand() % 5;
while (number == 0)
///如果是0就一直随机,直到出现不是0的为止
number = rand() % 5;
///tail_insert用尾插法初始化
s = new PCB;
s->pid = i + 1;
s->priority = (i + priority) % 5 + 1;
s->time = number;
if (s->priority != 5 || r->next == NULL)
///如果r->next== NULL表示为队列只有一个头结点,就直接插入
{ r->next = s;
r = s;}
if ((s->priority == 5) && (r->next != NULL))
///如果队列不为空,就将它放在头结点后面
{
s->next = L->next;
L->next = s;
}
}
r->next = NULL;}
void run(PCB L)///运行
{
PCB c = L; PCB p = L;
for (L; L; L = L->next)
{
if (L->next == NULL)
break;
///由于存在存在头结点,所以从L->next开始
L->next->priority = L->next->priority - 1;
L->next->time = L->next->time - 1;
if (L->next->time == 0){
///如果运行时间为0,就将它移除队列中 {
cout << “run over” <<"->PID->"<< L->next->pid << endl;
L->next->time = -1;
L->next = L->next->next;
///由于出现了L->next = L->next->next;这步,
///接着执行for循环的第三个表达式,便跳过了L->next->next这个结点,接着执行L->next->next->next这个结点
///所以需要判断一下L->next->next这个结点
if (L->next != NULL&&L->next->time != 0)
{ L->next->priority = L->next->priority - 1;
L->next->time = L->next->time - 1;
}
///如果L->next->next->time的值等于0,便会将它移除队列,接着执行L->next=L->next->next这步
///所以需要while循环来判断
四、实验结果
操作系统实验-设计一个按优先数调度算法实现处理器调度的程序
五、体会与收获
通过本次实验,我对优先数调度算法有了一定掌握。这道题慢悠悠地做,出现了很多错误,大多都是空指针产生的中断,最后还是实现了。希望以后自己在写代码的时候再仔细再认真一下。
六、源代码
#include
#include <time.h>
#include <stdlib.h>
using namespace std;
static int point = 0;
///用于计算进程是否运行完成
struct PCB{
int pid;
int priority;
int time;
PCB next;
};
void tailCreate(PCB L){
srand((unsigned int)time(0));
///以时间为随机数种子,保证每次随机数不一样
int priority = rand() % 5;///随机优先数
PCB s, r = L;
for (int i = 0; i<5; i++)
{ ///随机时间为1到50
int number = rand() % 5;
while (number == 0)
///如果是0就一直随机,直到出现不是0的为止
number = rand() % 5;
///tail_insert用尾插法初始化
s = new PCB;
s->pid = i + 1;
s->priority = (i + priority) % 5 + 1;
s->time = number;
if (s->priority != 5 || r->next == NULL)
///如果r->next==NULL表示为队列只有一个头结点,就直接插入
{
r->next = s;
r = s;
}
if ((s->priority == 5) && (r->next != NULL))
///如果队列不为空,就将它放在头结点后面
{
s->next = L->next;
L->next = s;
}
}
r->next = NULL;}
void run(PCB L)///运行
{
PCB c = L; PCB p = L;
for (L; L; L = L->next)
{
if (L->next == NULL)
break;
///由于存在存在头结点,所以从L->next开始
L->next->priority = L->next->priority - 1;
L->next->time = L->next->time - 1;
if (L->next->time == 0){
///如果运行时间为0,就将它移除队列中 {
cout << “run over” <<"->PID->"<< L->next->pid << endl;
L->next->time = -1;
L->next = L->next->next;
///由于出现了L->next = L->next->next;这步,
///接着执行for循环的第三个表达式,便跳过了L->next->next这个结点,接着执行L->next->next->next这个结点
///所以需要判断一下L->next->next这个结点
if (L->next != NULL&&L->next->time != 0)
{
L->next->priority = L->next->priority - 1;
L->next->time = L->next->time - 1;
}
///如果L->next->next->time的值等于0,便会将它移除队列,接着执行L->next=L->next->next这步
///所以需要while循环来判断
while (L->next != NULL&&L->next->time == 0)
{
cout << “run over” <<"->PID->"<< L->next->pid << endl;
L->next->time = -1;
L->next = L->next->next;
point = point + 1;
if (L->next != NULL)
{
L->next->priority = L->next->priority - 1;
L->next->time = L->next->time - 1;
}
}
point = point + 1;
}
if (L->next != NULL&&L->next->priority == 0)
///如果优先数为0就将它变成0放在队首
{ //

PCB q = L->next;
L->next = L->next->next;
q->priority = 5;
q->next = c->next;
c->next = q;
///由于执行了L->next=L->next->next
///所以又会执行上面那步同样地操作
if (L->next != NULL&&L->next->time != 0)
{
L->next->priority = L->next->priority - 1;
L->next->time = L->next->time - 1;
}
while (L->next != NULL&&L->next->time == 0)
{
cout << “run over” << “->PID->”<next->pid << endl;
L->next->time = -1;
L->next = L->next->next;
point = point + 1;
if (L->next != NULL)
{
L->next->priority = L->next->priority - 1;
L->next->time = L->next->time - 1;
}
}
}
}
L = p;
}
int main(){ PCB L, m; L = new PCB;
//初始化头结点
L->next = NULL; tailCreate(L);
m = L;
L = L->next;
cout << “=" << endl;
cout << “Init” << endl;
cout << "
==” << endl;
for (L; L; L = L->next)
{ cout <<“PID :”<< L->pid << endl;
cout << “Time :”<time << endl;
cout << “Priority :”<priority << endl;
cout << "
" << endl;
cout << endl; }
cout << "============= " << endl;
cout << “Init successful!” << endl;
cout << “==============” << endl;
cout << endl;
cout << “run order!” << endl;
while (point != 5)
{
run(m);
}
system(“pause”);
return 0; }