操作系统实验一 进程调度实验
题目描述:
1、 设计一个有N个进程并发的进程调度程序,每个进程由PCB
表示,PCB中包含进程名、优先数、服务时间等信息;
2、用链表表示就绪队列,每个进程PCB用结构体结点表示;
3、已知各进程的的到达时间等如下:
进程名 到达时间 服务时间 优先数
A 0 5 12
B 1 3 31
C 2 2 21
D 3 1 10
4、分别实现下面两种调度算法
•轮转调度
•优先级调度
3、实验结果输出格式(输出以下内容):
(1)优先级调度算法输出如下:
进程名、到达时间、服务时间、优先数、开始时间、完成时间、周转时间、带权周转时间,
每个进程一行
(2)轮转调度输出如下:(时间片为2)
t=… ,…执行
一、优先级调度算法:
1、算法思路:
① 根据示例图的运行结果可以知道,这里的优先级调度算法指的是静态非抢占式调度算法。
② 观察运行结果可以总结出以下调度规则:1)同一时间到的进程比较优先数决定谁先优先。2)一进程运行结束之后,查看已到达的进程,根据优先数决定哪一个进程是接下来要运行的。
③ 根据上述总结的规则,我采用一个计时器,将进程队列中到达时间与计时器相同的进程加入一个就绪队列,找出这个就绪队列中优先数最小的,运行该进程,并把它放进已完成执行的队列,并在原进程队列中标上已执行的标志。计时器时间设置为当前进程的完成时间,然后找到到达时间比计时器小的,而且没有被执行的进程没加入就绪队列,重复上述过程,直到所有进程执行完毕。
2、算法代码:
①生成优先级队列
ready_queue* first_number(ready_queue*&a)
{
int now_time = 0;//设置计时器,表示当前时间。
ready_queue* over_queue= (ready_queue*)malloc(sizeof(ready_queue));//完成队列
over_queue ->next= NULL;
ready_queue* rear_f = NULL;//就绪队列队尾
ready_queue* rear_o = NULL;//完成队列队尾
while (m != n)//判断是否执行完了所有的进程
{
ready_queue* p = a->next;
ready_queue* first= (ready_queue*)malloc(sizeof(ready_queue));
first->next = NULL;
while (p != NULL)
{
if (now_time >= p->data.arr_time & p->data.state == 0)//如果进程已到达,且未执行进入就绪队列
{
ready_queue*q= (ready_queue*)malloc(sizeof(ready_queue));
q->data.arr_time = p->data.arr_time;
q->data.name = p->data.name;
q->data.serve_time = p->data.serve_time;
q->data.first = p->data.first;
q->next = NULL;
if (first->next == NULL)
{
first->next = q;
rear_f = q;
}
else
{
rear_f->next = q;
q->prew = rear_f;
rear_f = q;
}
}
p = p->next;
}
//如果当前时间没有进程到达,当前时间+1。
if (first->next == NULL)
{
now_time++;
continue;
}
//找出优先数最小的进程进行执行。
ready_queue* z = first->next;
int low_first = z->data.first;
while (z != NULL)
{
if (z->data.first < low_first)
low_first = z->data.first;
z = z->next;
}
z = first->next;
while (z != NULL)
{
if (z->data.first == low_first)
break;
z = z->next;
}
z->data.start_time = now_time;
z->data.finish_time = z->data.start_time + z->data.serve_time;
z->data.total_time = z->data.finish_time -z->data.arr_time;
p = a->next;
//在原队列中将完成的进程设置为完成状态。
while (p != NULL)
{
if (p->data.name == z->data.name)
p->data.state = 1;
p = p->next;
}
m++;//计算当前完成的进程个数
now_time = z->data.finish_time;
ready_queue* f = (ready_queue*)malloc(sizeof(ready_queue));//复制进程信息
f->data.arr_time = z->data.arr_time;
f->data.name = z->data.name;
f->data.serve_time = z->data.serve_time;
f->data.finish_time = z->data.finish_time;
f->data.start_time = z->data.start_time;
f->data.first = z->data.first;
f->data.total_time = z->data.total_time;
f->data.state = 1;
f->next = NULL;
//加入完成进程队列。
if (over_queue->next == NULL)
{
over_queue->next = f;
rear_o = f;
}
else
{
rear_o->next = f;
f->prew = rear_o;
rear_o = f;
}
}
return over_queue;
}
②根据优先级队列输出相应的结果。
void display_first(ready_queue* a)
{
float p=0;
ready_queue* q = a->next;
while (q != NULL)
{
p = float(q->data.total_time) / q->data.serve_time;
cout << "进程名:" << q->data.name << " 到达时间:" << q->data.arr_time << " 优先数:" << q->data.first << " 开始时间:" << q->data.start_time <<" 完成时间:"<<q->data.finish_time<< " 周转时间:" << q->data.total_time << " 带权周转时间:" << p << endl;
q = q->next;
}
}
3、运行结果:
二、轮转调度算法:
1、算法思路:
① 这里把进程分为两个队列,一是具有所有队列信息的根据输入时进程顺序排列的原始进程队列,以下简称原队列;二是当前时间到达的进程的队列,为就绪队列。
② 首先在当前时间now_time扫描原队列,从头到尾进行扫描,把原队列中服务时间不为0的且到达时间小于或等于当前时间的进程加入到就绪队列中(复制一份过去,以免造成指针指向混乱)。
③ 取就绪队列中的队首进程执行,如果该进程的服务时间大于时间片,那么将其服务时间设置为原来服务时间减去时间片,并在原队列中找到相应进程更新服务时间,当前时间设置为now_time+时间片;反之,当前时间加上服务时间,将其服务时间设置为0,并在原队列中找到相应进程更新服务时间。完进程计数器+1。将执行过的进程从当前位置调到原队列的队尾,修改队尾指针。(这里队列采用带头和尾指针的双向链表,方便交换位置。)
④ 重复②③过程直到所有进程被执行完。
2、算法核心代码:
//轮转调度算法:
void turn_round(ready_queue*& a, int time_chip,ready_queue*& rear)
{
m = 0;//已完成的进程个数
int now_time=0;//当前时间计时器
while (m != n)
{
ready_queue* p = a->next;
ready_queue*q= (ready_queue*)malloc(sizeof(ready_queue));
q->next = NULL;
ready_queue* rear_q = NULL;
while (p != NULL)
{
if (p->data.arr_time <= now_time && p->data.serve_time != 0)//将符合条件的进程加入就绪队列
{
ready_queue*f= (ready_queue*)malloc(sizeof(ready_queue));
f->data.arr_time = p->data.arr_time;
f->data.name = p->data.name;
f->data.serve_time = p->data.serve_time;
f->next = NULL;
if (q->next == NULL)
{
q->next = f;
f->prew = q;
rear_q = f;
}
else
{
rear_q->next = f;
f->prew = rear_q;
rear_q = f;
}
}
p = p->next;
}
//如果当前时间没有满足的进程,当前时间+1进入下一个循环
if (q->next == NULL)
{
now_time++;
continue;
}
//执行就绪队列中的队首进程
p = q->next;
if (p->data.serve_time - time_chip > 0)
{
cout << "t=" << now_time <<"执行" << p->data.name << endl;
now_time += time_chip;
p->data.serve_time -= time_chip;
}
else
{
cout << "t=" << now_time << "执行" << p->data.name<< endl;
now_time += p->data.serve_time;
p->data.serve_time = 0;
m++;
}
//找到原队列中相应的进程,修改相关数据
ready_queue* z = a->next;
while (z != NULL)
{
if (z->data.name == p->data.name)
{
z->data.serve_time = p->data.serve_time;
break;
}
z = z->next;
}
//将执行过的进程从当前位置调到原队列的队尾,修改队尾指针
z->prew->next = z->next;
z->next->prew = z->prew;
rear->next = z;
z->prew = rear;
rear = z;
rear->next = NULL;
}
cout << "进程执行完毕!" << endl;
}
3、运行结果:
注:上述实现算法从解决题目要求的结果出发,可能会考虑不周,而且没有考虑优化时间复杂度和空间复杂度。请多指教。