1、题目简介

  1. 给出进程调度的算法描述(如基于动态优先级和时间片轮转调度算法的描述)。用C语言设计一个对n个并发进程进行调度的程序,每个进程由一个进程控制块(PCB)结构表示,该进程控制块应包括下述信息:进程标识ID、进程优先数PRIORITY(并规定优先数与优先权成正比)、时间片数CHIP、进程已经占用CPU的时间CPUTIME,进程还需要运行的时间ALLTIME(当进程运行完毕时,其值为0)、进程的状态STATE(为简化起见。设每个进程处于运行E(excecuting)、就绪R(ready)和完成F(finish)三种状态之一,并假设起始状态都是就绪状态R。),以及进程队列指针NEXT(用来将PCB排成队列)等,可按照调度算法的不同而增删。
  2. 调度程序应当包含2种不同的调度算法,运行时可以任选一种,以利于各种方法的分析和比较。
  3. 程序应能显示或打印各种进程状态和参数变化情况,便于观察。即要显示每个时间片内各进程的情况,并且指出运行进程及就绪和阻塞队列中的内容。

2、参考设计思路

进程控制块(PCB)的定义如下:

typedef struct process_pcb
{
	int ID;				//进程标识
	int priority;		//进程优先数,值越大,优先级越高
	int arrive_time;	//进程达到时间,以时间片为单位
	int service_time;	//进程需要总的服务时间,以时间片为单位
	int start_time;		//进程开始执行时间,以时间片为单位
	int end_time;		//进程结束时间,以时间片为单位
	int all_time;		//进程仍然需要运行时间,以时间片为单位
	int cpu_time;		//进程已占用cpu时间,以时间片为单位
	STATE state;		//进程状态
}

3、所有的函数定义:

//排序比较函数:按照进程到达时间升序排列
bool cmp_arrive_time(const PCB a, const PCB b);
//排序比较函数:按照进程优先数降序排序
bool cmp_priority(const PCB a, const PCB b);
//输入进程信息
void input_process();
//选择进程调度策略
int select_policy();
//打印所有进程信息
void print_all(int current);
//先来先服务算法
void FCFS();
//时间片轮转算法
void round_robin();
//动态优先级算法
void dynamic_prio();

4、具体代码如下:

#include <iostream>
#include <queue>

using namespace std;

//进程三种状态,这里增加一种,表示虽然输入,但是还没有到达进入系统时刻
typedef enum ProcessState{Executing, Ready, Finish, Unarrive}STATE;
//用于打印进程三种状态
char* StateString[] = {"Executing", "Ready", "Finish", "--"};

typedef struct process_pcb
{
	int ID;				//进程标识
	int priority;		//进程优先数,值越大,优先级越高
	int arrive_time;	//进程到达时间,以时间片为单位
	int service_time;	//进程需要总的服务时间
	int start_time;		//进程开始执行时间
	int end_time;		//进程结束时间
	int all_time;		//进程仍然需要运行时间
	int cpu_time;		//进程已占用cpu时间 
	STATE state;	//进程状态
}PCB;

//排序比较函数:按照进程到达时间升序排列
bool cmp_arrive_time(const PCB a, const PCB b);
//排序比较函数:按照进程优先数降序排序
bool cmp_priority(const PCB a, const PCB b);
//输入进程信息
void input_process();
//选择进程调度策略
int select_policy();
//打印所有进程信息
void print_all(int current);
//先来先服务算法
void FCFS();
//时间片轮转算法
void round_robin();
//动态优先级算法
void dynamic_prio();

PCB *running_process = NULL;//当前运行任务
vector<PCB> input_queue;//进程输入队列,如当前时刻小于进程到达时间,则该进程仍然在输入队列中
vector<PCB> ready_queue;//就绪队列
vector<PCB> finish_queue;//完成队列

int main()
{
	printf("===================================================\n");
	printf("              操作系统进程调度模拟实验             \n");
	printf("===================================================\n");
	printf("\n");
	input_process();
	//-1标志为打印所有进程的初始状态
	print_all(-1);
	int policy = select_policy();
	switch(policy)
	{
	case 1:
		FCFS();
		break;
	case 2:
		round_robin();
		break;
	case 3:
		dynamic_prio();
		break;
	default:
		FCFS();
		break;
	}
}

//按进程到达时间升序排列,先到达的排在队首
bool cmp_arrive_time(const PCB a, const PCB b)
{
	return a.arrive_time < b.arrive_time;
}
//按进程优先级降序排列,优先级高的排在队首
//如优先级相同,先到的进程排在前面
bool cmp_priority(const PCB a, const PCB b)
{
	if(a.priority != b.priority){
		return a.priority > b.priority;
	}else{
		return a.arrive_time < b.arrive_time;
	}
}

//选择进程调度策略
int select_policy()
{
	printf("\n请选择调度算法(输入1、2、3选择):\n");
	printf("1.先来先服务调度(FCFS)              \n");
	printf("2.时间片轮转调度(Round-Robin)       \n");
	printf("3.动态优先级调度(DynamicPriority)   \n");
	int n;
	printf("请输入调度算法序号:");
	while(scanf("%d",&n)){
		if(n > 3 || n < 1){
			printf("对不起,输入有误,请重新输入!\n");
		}else{
			break;
		}
	}
	return n;
}

//输入进程信息
void input_process()
{
	int num;
	printf("请输入进程数量:");
	scanf("%d",&num);
	PCB	pro;
	for(int i = 1; i <= num; i++){
		printf("\n请输入第%d个进程的到达时间、服务时间及优先级(以空格隔开):\n",i);
		scanf("%d%d%d",&pro.arrive_time,&pro.service_time,&pro.priority);
		pro.ID = i;
		pro.all_time = pro.service_time;
		pro.cpu_time = 0;
		pro.start_time = -1;//开始时间、结束时间默认为-1,表示尚未被调度过
		pro.end_time = -1;
		pro.state = Unarrive;//初始化为尚未进入到达
		input_queue.push_back(pro);
	}
	//按照到达时间升序排队
	sort(input_queue.begin(), input_queue.end(), cmp_arrive_time);
}
//打印单个进程的信息
void print_process(PCB* pro)
{
	if(pro == NULL){
		return;
	}
	printf("%4d%10d%10d%8d%10s", pro->ID, pro->arrive_time, pro->service_time, pro->priority, StateString[pro->state]);
	//如进程尚未开始,则开始时间、结束时间以及剩余时间以--表示
	//如进程已经开始,但未结束,则其结束时间以--表示
	if(pro->start_time == -1){
		printf("%10s%10s%10s", "--", "--", "--");
	}else{
		if(pro->end_time == -1){
			printf("%10d%10s%10d", pro->start_time, "--", pro->all_time);
		}else{
			printf("%10d%10d%10d", pro->start_time, pro->end_time, pro->all_time);
		}
	}
	//仅进程结束后,才统计其周转时间及加权周转时间
	if(pro->state == Finish)
	{
		printf("%10d%10.2lf\n", pro->end_time - pro->arrive_time, (float)(pro->end_time - pro->arrive_time)/(float)pro->service_time);
	}else{
		printf("%10s%10s\n", "--", "--");
	}
}
//打印所有进程的信息,-1为打印进程初始输入状态
void print_all(int current)
{
	if(current == -1){
		printf("\n进程初始状态:\n", current);
	}else{
		printf("\n当前时刻为:%d\n", current);
	}
	printf("进程号  到达时间  服务时间  优先级    状态    开始时间  结束时间  剩余时间  周转时间  带权周转时间\n");
	//打印正在运行的进程
	if(running_process != NULL){
		print_process(running_process);
	}
	vector<PCB>::iterator it;
	//打印就绪队列中的进程
	for(it = ready_queue.begin(); it != ready_queue.end(); it ++){
		print_process(&(*it));
	}
	//打印完成队列中的进程
	for(it = finish_queue.begin(); it != finish_queue.end(); it ++){
		print_process(&(*it));
	}
	//打印仍在输入队列中的进程
	for(it = input_queue.begin(); it != input_queue.end(); it ++){
		print_process(&(*it));
	}
}
//先来先服务算法
void FCFS()
{
	int chip = 0;//初始的时间片为0
	//需要调度标志,默认为true
	bool need_schedule = true;
	while(1)
	{
		//如当前无正在运行进程,同时输入队列和就绪队列都为空,则所有进程完成
		if(!running_process && input_queue.empty() && ready_queue.empty()){
			break;
		}
		//将输入队列中,到达时间小于等于当前时间片的进程放入就绪队列中,并从输入队列中删除
		while(!input_queue.empty()){
			PCB pro = input_queue[0];
			if(pro.arrive_time <= chip){
				pro.state = Ready;
				//放入就绪队列队尾
				ready_queue.push_back(pro);
				//从输入队列中删除
				input_queue.erase(input_queue.begin() + 0);
			}else{
				break;
			}
		}
		//判断是否需要调度,如需要则从取出就绪队列队首进程进行调度
		if(need_schedule && !ready_queue.empty())
		{
			running_process = new PCB;
			*running_process = ready_queue[0];//取出就绪队首进程
			ready_queue.erase(ready_queue.begin() + 0);//从就绪队列中删除之
			//调度进程开始运行
			running_process->start_time = chip;
			running_process->state = Executing;
			need_schedule = false;
		}
		print_all(chip);//打印当前时刻所有进程的信息
		//当前运行任务完成1个时间片,更改其信息
		if(running_process){
			running_process->cpu_time += 1;
			running_process->all_time -= 1;
			if(running_process->all_time == 0){//任务运行结束
				running_process->end_time = chip + 1;
				running_process->state = Finish;
				finish_queue.push_back(*running_process);//将其放入完成队列中
				delete running_process;
				running_process = NULL;
				need_schedule = true;
			}else{
				//FCFS仅当该进程运行完毕后,才调度下一个任务
				need_schedule = false;
			}
		}
		chip += 1;
	}
	//所有任务全部完成后,打印一次
	print_all(chip);
}

//时间片轮转算法
void round_robin()
{
	int chip = 0;//初始的时间片为0
	bool need_schedule = true;
	while(1)
	{
		//如当前无正在运行进程,同时输入队列和就绪队列都为空,则所有进程完成
		if(!running_process && input_queue.empty() && ready_queue.empty()){
			break;
		}
		//将输入队列中,到达时间小于等于当前时间片的进程放入就绪队列中,并从输入队列中删除
		while(!input_queue.empty()){
			PCB pro = input_queue[0];
			if(pro.arrive_time <= chip){
				pro.state = Ready;
				//放入就绪队列队尾
				ready_queue.push_back(pro);
				//从输入队列中删除
				input_queue.erase(input_queue.begin() + 0);
			}else{
				break;
			}
		}
		//判断是否需要调度,如需要则取出就绪队列队首进程进行调度
		if(need_schedule && !ready_queue.empty())
		{
			running_process = new PCB;
			*running_process = ready_queue[0];//从就绪队首中取出
			ready_queue.erase(ready_queue.begin() + 0);//从就绪队列中删除之
			//调度进程开始运行
			if(running_process->start_time == -1){//首次运行
				running_process->start_time = chip;
			}
			running_process->state = Executing;
			need_schedule = false;
		}
		print_all(chip);//打印当前时刻所有进程的信息
		//当前运行任务完成1个时间片,判断该任务是否已经完成
		if(running_process){
			running_process->cpu_time += 1;
			running_process->all_time -= 1;
			if(running_process->all_time == 0){//任务运行结束
				running_process->end_time = chip + 1;
				running_process->state = Finish;
				finish_queue.push_back(*running_process);//将其放入完成队列中
				delete running_process;
				running_process = NULL;
				need_schedule = true;
			}else{//任务没有完成,如果就绪队列中仍有任务,则轮转调度,否则不调度
				if(!ready_queue.empty()){
					running_process->state = Ready;
					ready_queue.push_back(*running_process);//将其放回就绪队列中
					delete running_process;
					running_process = NULL;
					need_schedule = true;
				}else{
					need_schedule = false;
				}
			}
		}
		chip += 1;
	}
	//所有任务全部完成后,打印一次
	print_all(chip);
}

//动态优先级算法
void dynamic_prio()
{
	int chip = 0;//初始的时间片为0
	bool need_schedule = true;
	while(1)
	{
		//如当前无正在运行进程,同时输入队列和就绪队列都为空,则所有进程完成
		if(!running_process && input_queue.empty() && ready_queue.empty()){
			break;
		}
		//将输入队列中,到达时间小于等于当前时间片的进程放入就绪队列中,并从输入队列中删除
		while(!input_queue.empty()){
			PCB pro = input_queue[0];
			if(pro.arrive_time <= chip){
				pro.state = Ready;
				//放入就绪队列队尾
				ready_queue.push_back(pro);
				//从输入队列中删除
				input_queue.erase(input_queue.begin() + 0);
			}else{
				break;
			}
		}
		if(!ready_queue.empty()){
			//将就绪进程按照优先级降序排列
			sort(ready_queue.begin(), ready_queue.end(), cmp_priority);
		}
		//判断是否需要调度,如需要则取出就绪队列队首进程进行调度
		if(need_schedule && !ready_queue.empty())
		{
			running_process = new PCB;
			*running_process = ready_queue[0];//取出就绪队首进程
			ready_queue.erase(ready_queue.begin() + 0);//从就绪队列中删除之
			//调度进程开始运行
			if(running_process->start_time == -1){//首次运行
				running_process->start_time = chip;
			}
			running_process->state = Executing;
			need_schedule = false;
		}
		print_all(chip);//打印当前时刻,所有进程的信息
		//当前运行任务完成1个时间片,判断该任务是否已经完成
		if(running_process){
			running_process->cpu_time += 1;
			running_process->all_time -= 1;
			if(running_process->all_time == 0){//任务运行结束
				running_process->end_time = chip + 1;
				running_process->state = Finish;
				finish_queue.push_back(*running_process);//将其放入完成队列中
				delete running_process;
				running_process = NULL;
				need_schedule = true;
			}else{//任务没有完成,如果就绪队列中仍有任务,且优先级大于本任务的优先级,则轮转调度,否则不调度
				if(running_process->priority > 1){
					running_process->priority -= 1;//优先级最小为1
				}
				if(!ready_queue.empty() && ready_queue[0].priority > running_process->priority){
					running_process->state = Ready;
					ready_queue.push_back(*running_process);//将其放回就绪队列中
					delete running_process;
					running_process = NULL;
					need_schedule = true;
				}else{
					need_schedule = false;
				}
			}
		}
		chip += 1;
	}
	//所有任务全部完成后,打印一次
	print_all(chip);
}

 

Logo

更多推荐