操作系统 实验一 进程调度实验

操作系统实验一 进程调度实验

题目描述:
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、运行结果:
在这里插入图片描述
注:上述实现算法从解决题目要求的结果出发,可能会考虑不周,而且没有考虑优化时间复杂度和空间复杂度。请多指教。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值