【操作系统实验 / C++】设计一个按时间片轮转法实现处理器调度的程序(附代码)

1、选题及题目要求

设计一个按时间片轮转法实现处理器调度的程序

(1) 假定系统有5个进程,每个进程用一个PCB来代表。PCB的结构为:

1、进程名——如Q1~Q5。

2、指针——把5个进程连成队列,用指针指出下一个进程PCB的首地址。

3、要求运行时间——假设进程需要运行的时间单位数。

4、已运行时间——进程已运行的时间单位数,初始值为0。

5、状态——假设两种状态,就绪和结束,用R表示就绪,用E表示结束。初始状态都为就绪状态。

(2) 运行之前,为每个进程确定它的“要求运行时间”。通过键盘输入这些参数。

(3) 把5个进程按顺序排成循环队列,用指针指出队列连接情况。用一个标志单元记录轮到运行的进程。处理器调度总是选择标志单元指示的进程运行,对所指的进程,将其“已运行时间”加1。

(4) 进程运行一次后,若“要求运行时间”等于“已运行时间”,则将状态改为“结束”,退出队列,否则将继续轮转。

(5) 若就绪队列为空,结束,否则转到(3)重复。

​ 要求能接受键盘输入的进程要求运行时间,能显示每次进程调度的情况,如哪个进程在运行,哪些进程就绪,就绪进程的排列情况。

2、数据结构设计

根据题目要求,设计了一组指针结构的数据,用于存储每一个进程。

typedef struct node 

{ 
	int process_num;    //进程名(数字)  
	struct node *next;   //下一进程地址指针  
	int required_time;   //要求运行时间  
	int processed_time;   //已运行时间  
	bool status;      //当前状态,0为就绪,1为结束  
}pcb_node;

​ 在程序开始时,通过 create_pcb() 函数来动态链接五个进程,使指针结构首尾相连,然后在 input_pcb() 函数中初始化函数数据,依次输入进程要求运行时间,并存储。

3、程序主要思路和原理

主要思路:利用指针结构连接成循环链表,并且采用头指针(前置一位的指针)的思路,每一步修改当前指针的下一指针结构的内容,以避免在运算过程中需要改变循环结构时(即某一进程完成后将其从循环队列中剔除)的问题。

时间片默认为1,每一次操作将 required_time 减1,processed_time加1,随后检测当前进程是否完成,若完成则将其退出队列,当前指针连接至下下一个指针;若没有完成则将指针指向下一个。

原理:循环链表,指针

4、程序运行结果

任意输入一组时间数据,运行结果如下:

在这里插入图片描述
在这里插入图片描述

可见,未出现程序错误,且调度结果正常,该实验完成。

5、详细代码

#include <iostream>
using namespace std;

typedef struct node
{
	int process_num;		//进程名(数字) 
	struct node *next;		//下一进程地址指针 
	int required_time;		//要求运行时间 
	int processed_time;		//已运行时间 
	bool status;			//当前状态,0为就绪,1为结束 
}pcb_node;


void create_pcb(pcb_node *first, pcb_node *second, pcb_node *third, pcb_node *fourth, pcb_node *fifth)
{	
	//按照要求初始化 pcb 
	first->next = second;
	first->process_num = 1;
	first->processed_time = 0;
	first->status = 0;
	
	second->next = third;
	second->process_num = 2;
	second->processed_time = 0;
	second->status = 0;
	
	third->next = fourth;
	third->process_num = 3;
	third->processed_time = 0;
	third->status = 0;
	
	fourth->next = fifth;
	fourth->process_num = 4;
	fourth->processed_time = 0;
	fourth->status = 0;
	
	fifth->next = first;			//构成循环队列 
	fifth->process_num = 5;
	fifth->processed_time = 0;
	fifth->status = 0;
}


void input_pcb(pcb_node *first)		//输入每个进程的要求运行时间 
{
	pcb_node *temp = new pcb_node();
	temp = first;
	int i,time;
	cout<<"***************输入要求运行时间***************"<<endl;
	
	for(i=1;i<=5;i++)
	{
		cout<<endl<<"请输入第"<<i<<"个进程的要求运行时间:";
		cin>>time;
		temp->required_time = time;
		temp = temp->next;
	}
}


void run_pcb(pcb_node *first)
{
	pcb_node *temp = new pcb_node();
	temp->next = first;
	cout<<endl<<"*******************进程调度*******************";
	int i;
	
	for(i=1;i<=50;i++)				//显示每一次进程调度的情况 
	{
		cout<<endl<<endl<<"**程序第"<<i<<"次调度**";
		cout<<endl<<"当前进程:Q"<<temp->next->process_num;
		cout<<endl<<"就绪进程:";
		pcb_node *check = new pcb_node();
		check = temp->next;
		int ready_num = 0;
		
		while(check->next != temp->next)	//按序输出就绪进程队列 
		{
			check = check->next;
			if(check->status == 0)
			{
			cout<<"Q"<<check->process_num<<";";
			ready_num = ready_num + 1;
			}
		}
		
		if(ready_num == 0 && temp->next->status == 0)	//针对只剩下一个进程的情况 
		{
			cout<<"当前无就绪进程";
			int j;
			for(j=1;j<temp->next->required_time;j++)
			{
				cout<<endl<<endl<<"**程序第"<<i+j<<"次调度**";
				cout<<endl<<"当前运行进程:Q"<<temp->next->process_num;
			}
			cout<<endl<<endl<<"*****************全部调度完成*****************"<<endl;
			break;
		}
		
		temp->next->required_time --;
		temp->next->processed_time ++;
		
		if(temp->next->required_time == 0)		//退出进程 
		{
			if(i == 1)		//针对第一次调度去掉Q1的情况 
			{
				temp->next->next->next->next->next->next = temp->next->next;
			}
			temp->next->status = 1;
			cout<<endl<<"Q"<<temp->next->process_num<<"进程结束,退出队列";
			cout<<endl<<"该进程的运行时间为:"<<temp->next->processed_time;
			temp->next = temp->next->next; 
			continue;
		}
		
		temp = temp->next;
	}
} 


int main()
{
	pcb_node *first = new pcb_node();
	pcb_node *second = new pcb_node();
	pcb_node *third = new pcb_node();
	pcb_node *fourth = new pcb_node();
	pcb_node *fifth = new pcb_node();		//固定创立五个进程指针 
	
	cout<<"说明:共有五个进程,按照时间片轮转算法进行调度运算,下面进行初始化。"<<endl<<endl; 
	
	create_pcb(first, second, third, fourth, fifth);
	
	input_pcb(first);
	
	run_pcb(first);
	
	system("pause");
	return 0;
}

注:水平较菜,可能存在代码不简洁的部分,但是代码实测是可以跑的,仅供思路参考~

[提示] (1)假定系统有五个进程,每一个进程用一个进程控制块PCB来代表。进程控制块的格式为: 进程名 指针 要求运行时间 已运行时间 状态 其中,进程名----作为进程的标识,假设五个进程的进程名分别是Q1,Q2,Q3,Q4,Q5。 指针----进程按顺序排成循环队列,用指针指出下一个进程的进程控制块首地址,最后一个进程中的指针指出第一个进程的进程控制块首地址。 要求运行时间----假设进程需要运行的单位时间。 已运行时间----假设进程已经运行的单位时间,初始值为“0”。 状态----有两种状态,“就绪”状态和“结束”状态,初始状态都为“就绪”,用“R”表示,当一个进程运行结束后,它的状态变为“结束”,用“E”表示。 (2)每次运行你所设计处理器调度程序之前,为每个进程任意确定它的“要求运行时间”。 把五个进程按顺序排成循环队列,用指针指出队列连接情况。另用一标志单元记录轮到运行的进程。 (3)处理器调度总是选择标志单元指示的进程运行。由于本实验是模拟处理器调度的功能,所以,对被选中的进程并不实际启动运行,而是执行: 已运行时间-1 来模拟进程的一次运行,表示进程已经运行过一个单位的时间。 请注意:在实际的系统中,当一个进程被选中运行时,必须置上该进程可以运行的时间片值,以及恢复进程的现场,让它占有处理器运行,直到出现等待事件或运行满一个时间片。在这里省去了这些工作,仅用“已运行时间+1”来表示进程已经运行满一个时间片。 (4)进程运行一次后,应把该进程的进程控制块中的指针值送到标志单元,以指示下一个轮到运行的进程。同时,应判断该进程的要求运行时间与已运行时间,若该进程要求运行时间≠已运行时间,则表示它尚未执行结束,应待到下一轮时再运行。若该进程的要求运行时间=已运行时间,则表示它已经执行结束,应把它的状态修改为“结束”(E)且退出队列。此时,应把该进程的进程控制块中的指针值送到前面一个进程的指针位置。 (5)若“就绪”状态的进程队列不为空,则重复上面(4)和(5)的步骤,直到所有进程都成为“结束”状态。 (6)在所设计的称序中应有显示或打印语句,能显示或打印每次被选中进程的进程名以及运行一次后进称对列的变化。 (7)为五个进程任意确定一组“要求运行时间”,启动所设计处理器调度程序,显示或打印逐次被选中进程的进程名以及进程控制块的动态变化过程。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值