操作系统:进程调度模拟,C语言实现

作业要求 【题目要求】模拟实现进程调度的经典算法,包括FCFS、SJF(SPF)、HRRN和RR(时间片大小分别为1和4)。输出调度过程,并计算不同调度算法的周转时间、平均周转时间、带权周转时间、平均带权周转时间、等待时间、平均等待时间等信息。
【实习要求】 可选编程语言:C/C++/Java/C#/Python;
实现在同一个程序文件中(C/C++);
请适当注释;
【实现提示】
可以用链式存储结构实现,推荐实现一个队列数组(queue array),该数组的每个元素都代表一个长度可变的队列,队列中的每个元素则代表一个任务job,任务结构定义(可修改)如下:
typedef struct Job {
int job_pid; //任务号
int arrive_time; //到达时间
int burst; //运行时间
int end_time; //完成时间
int cycle_time; //周转时间
int waited_time; //等待时间
int w_cycle_time; //带权等待时间
struct Job *next;
} Job;
【测试数据】
输入:任务号 到达时间 运行时间
输出:任务号 响应时间 完成时间 周转时间 …
××××算法平均周转时间、平均等待时间、平均带权周转时间…

首先输入例题并测试结果,例题如下:

除例题外,报告上要求写出多批自拟数据测试结果。

代码如下:(运行环境:VS2019)

#include
#include
#include



#define TRUE 1
#define FALSE 0
#define LEN 5
typedef struct job
{
	int PID;//ID
	int arriveTime;//到达时间
	int requireTime;//要求服务时间
	int usedTime;//已使用时间
	int endedTime;//结束时间
	int waitedTime;//等待时间
	int cycleTime;//周转时间
	float weightCycleTime;//带权周转时间
	struct job *next;
	
}Job;

typedef struct linkedqueue
{
	Job* front;
	Job* rear;
	int count;
}LinkedQueue;

Job jobArray[LEN];
//后备队列
LinkedQueue* createdQueue;
//就绪队列
LinkedQueue* readyQueue;
//完成队列
LinkedQueue* endedQueue;

void printMenu();//打印菜单
void initJobs(Job*);//初始化作业
void initQueue();//初始化队列
void fcfsJobs();//先来先服务算法
void enQueueNode(LinkedQueue*, Job*);//入队操作,尾插法
Job* deQueue(LinkedQueue*);//出队头操作
int is_empty(LinkedQueue*);//判空函数
void recordJobTime(Job*);//记录各个时间
void printAvgValue();//打印出平均数值
Job* peekQueue(LinkedQueue*);//返回队列头
void sjfJobs();//最短作业优先发
void rrJobs(int);//时间片轮转法
void hrrnJobs();//高相应比算法
Job* findShortestJob(LinkedQueue*);//找到最短作业
Job* findHighestestJob(LinkedQueue*);//找到最高相应比作业
void CacluateWaitedTime(LinkedQueue*);//计算当前作业等待时间


int main()
{
	char userOpt;
	while (1)
	{
		//初始化作业;
		initJobs(jobArray);
		//初始化队列;
		initQueue();
		//打印菜单
		printMenu();
		scanf_s("%c", &userOpt, sizeof(userOpt));
		getchar();
		switch (userOpt)
		{
		case '1':
			fcfsJobs();
			break;
		case '2':
			sjfJobs();
			break;
		case '3':
			rrJobs(1);
			break;
		case '4':
			rrJobs(4);
			break;
		case '5':
			hrrnJobs();
			break;
		case 'q':
			exit(0);
			break;

		}
	}
	return 66;
	
}

void printMenu()
{
	printf("按1FCFS\n");
	printf("按2SJF\n");
	printf("按3时间片轮转 q=1\n");
	printf("按4时间片轮转 q=4\n");
	printf("按5HRRN\n");
	printf("按q退出\n");
	printf("你的选择:\n");
	printf("\n==================\n");

}
void initJobs(Job* jobArray)
{
	jobArray[0].PID = 0;
	jobArray[0].requireTime = 3;
	jobArray[0].arriveTime = 0;
	jobArray[0].endedTime = -1;
	jobArray[0].usedTime = 0;

	jobArray[1].PID = 1;
	jobArray[1].requireTime = 6;
	jobArray[1].arriveTime = 2;
	jobArray[1].endedTime = -1;
	jobArray[1].usedTime = 0;

	jobArray[2].PID = 2;
	jobArray[2].requireTime = 4;
	jobArray[2].arriveTime = 4;
	jobArray[2].endedTime = -1;
	jobArray[2].usedTime = 0;

	jobArray[3].PID = 3;
	jobArray[3].requireTime = 5;
	jobArray[3].arriveTime = 6;
	jobArray[3].endedTime = -1;
	jobArray[3].usedTime = 0;

	jobArray[4].PID = 4;
	jobArray[4].requireTime = 2;
	jobArray[4].arriveTime = 8;
	jobArray[4].endedTime = -1;
	jobArray[4].usedTime = 0;

}

void initQueue()
{
	free(createdQueue);
	free(readyQueue);
	free(endedQueue);
	createdQueue = (LinkedQueue*)malloc(sizeof(LinkedQueue));
	endedQueue = (LinkedQueue*)malloc(sizeof(LinkedQueue));
	readyQueue = (LinkedQueue*)malloc(sizeof(LinkedQueue));
	
	if (createdQueue != NULL && endedQueue != NULL && readyQueue != NULL)
	{//判空,是否创建成功
		createdQueue->front = createdQueue->rear = NULL;
		readyQueue->front = readyQueue->rear = NULL;
		endedQueue->front = endedQueue->rear = NULL;
		printf("\n");
	}
	int i;
	for (i = 0;i < LEN;i++)
	{
		enQueueNode(createdQueue, &jobArray[i]);
	}

}

void fcfsJobs()
{
	int currentTime = 0;
	Job* runningJob = NULL;
	while (!is_empty(createdQueue) || !is_empty(readyQueue) || runningJob != NULL)
	{
		while (!is_empty(createdQueue))
		{//进入就绪队列操作
			//返回队头作业
			Job* frontJob = peekQueue(createdQueue);
			if (frontJob->arriveTime == currentTime)
			{
				//后备出第一个挂入就绪队列
				enQueueNode(readyQueue, deQueue(createdQueue));

			}
			else {
				break;
			}
		}

		if (runningJob == NULL)
		{
			if (!is_empty(readyQueue))
			{
				runningJob = deQueue(readyQueue);
			}
			else
			{
				printf("系统%d时刻就绪队列为空\n", currentTime);
				currentTime++;
				continue;
			}
		}
		else
		{
			if (runningJob->usedTime == runningJob->requireTime)
			{
				runningJob->endedTime = currentTime;
				enQueueNode(endedQueue, runningJob);
				recordJobTime(runningJob);
				printf("作业%d已完成,完成时间:%d 等待时间%d\n", runningJob->PID, runningJob->endedTime,runningJob->waitedTime);

				if (!is_empty(readyQueue)) {
					runningJob = deQueue(readyQueue);
				}

				else {
					runningJob = NULL;
				}
			}
			else
			{

			}

		}
		currentTime++;
		
		//CacluateWaitedTime(readyQueue);
		if (runningJob != NULL)
		{
			runningJob->usedTime++;
		}
	}

	printf("FCFS的调度信息:\n");
	printAvgValue();
}

void enQueueNode(LinkedQueue* queue, Job* job)
{//插入队尾
	if (is_empty(queue))
	{//队列为空时进队
		queue->front = queue->rear = job;
		job->next = NULL;
	}
	else
	{//非空时
		queue->rear->next = job;
		queue->rear = job;
		queue->rear->next = NULL;
	}
}

Job* deQueue(LinkedQueue* queue)
{//出队函数 出队头
	//临时变量存储队头的地址
	Job* returnJob;
	if (is_empty(queue))
	{//若队列为空
		printf("队列为空,无法出列\n");
		return NULL;
	}
	//不为空时
	returnJob = queue->front;
	if (queue->front == queue->rear)
	{//若只有一个节点
		queue->front = queue->rear = NULL;
	}
	else
	{//多于一个节点
		queue->front = queue->front->next;
	}
	returnJob->next = NULL;
	return returnJob;
}

int is_empty(LinkedQueue* queue)
{//判空,1为空,0为非空
	if (queue->front == NULL&& queue->rear==NULL)
	{
		return TRUE;
	}
	else
	{
		return FALSE;
	}
}

void recordJobTime(Job* runningJob)
{//计算当前作业的周转时间,等待时间,带权周转时间
	runningJob->cycleTime = runningJob->endedTime - runningJob->arriveTime;
	runningJob->waitedTime = runningJob->cycleTime - runningJob->requireTime;
	runningJob->weightCycleTime = (float)runningJob->cycleTime 
		                                    /
		                         (float)runningJob->requireTime;
}

void printAvgValue()
{//打印每个作业的平均值
	float avgCycleTime = 0;
	float avgWaitedTime = 0;
	float avgWeightCycleTime = 0;
	int i;
	for (i = 0;i < LEN;i++)
	{
		avgCycleTime += (float)jobArray[i].cycleTime;
		avgWaitedTime += (float)jobArray[i].waitedTime;
		avgWeightCycleTime += jobArray[i].weightCycleTime;
	}
	avgCycleTime = avgCycleTime / (float)LEN;
	avgWaitedTime = avgWaitedTime / (float)LEN;
	avgWeightCycleTime = avgWeightCycleTime / (float)LEN;

	printf("平均周转时间%05.2f  平均等待时间:%05.2f 平均带权周转时间:%05.2f\n"
		, avgCycleTime, avgWaitedTime, avgWeightCycleTime);
}

Job* peekQueue(LinkedQueue* queue)
{
	return queue->front;
}

void sjfJobs()
{
	int currentTime = 0;
	Job* runningJob = NULL;
	while (!is_empty(createdQueue) || !is_empty(readyQueue) || runningJob != NULL)
	{
		while (!is_empty(createdQueue))
		{
			Job* frontJob = peekQueue(createdQueue);
			if (frontJob->arriveTime == currentTime)
			{
				enQueueNode(readyQueue, deQueue(createdQueue));
			}
			else
			{
				break;
			}
		}

		if (runningJob == NULL)
		{
			if (!is_empty(readyQueue))
			{
				runningJob = findShortestJob(readyQueue);
			}
			else
			{
				printf("系统%d时刻就绪队列为空\n", currentTime);
				currentTime++;
				continue;
			}
		}
		else
		{
			if (runningJob->usedTime == runningJob->requireTime)
			{
				runningJob->endedTime = currentTime;
				enQueueNode(endedQueue, runningJob);
				recordJobTime(runningJob);
				printf("作业%d已完成,完成时刻%d 等待时间%d\n", runningJob->PID, runningJob->endedTime,runningJob->waitedTime);

				if (!is_empty(readyQueue))
				{
					runningJob = findShortestJob(readyQueue);
					
				}
				else
				{
					runningJob = NULL;
					
				}
			}
			else
			{
				//若当前作业还未完成,则什么都不做,在下面走一步
				
			}
		}
		currentTime++;
		
		
		if (runningJob != NULL)
		{
			runningJob->usedTime++;
		}
	}

	printf("sjfsJob调度信息:\n");
	printAvgValue();
}

Job* findShortestJob(LinkedQueue *readyQueue)
{
	Job* returnJob=NULL,*head;
	head = readyQueue->front;
	if (readyQueue->front != NULL)
	{//就绪对列不为空
		if (head->next == NULL)
		{//若就绪队列只有一个
			returnJob = head;
			returnJob->next = NULL;
			readyQueue->front = readyQueue->rear=NULL;
			return returnJob;
		}
		else
		{//若队列中不止一个
			returnJob = head;
			while (head->next!= NULL)
			{//循环整个就绪队列,记下最短Job
				
				if (returnJob->requireTime > head->next->requireTime)
				{
					returnJob = head->next;
					head = head->next;
					
				}
				else
				{
					head = head->next;
				}
			}
			//循环之后head返回就绪队列队头
			head = readyQueue->front;
			if (head == returnJob)
			{//若返回的JOB是在队头
				head = head->next;
				//不要忘记变更就绪队列的队头!!!
				readyQueue->front = head;
				returnJob->next = NULL;
				return returnJob;
			}
			else
			{//返回的JOB不在队头
				while (head->next != returnJob)
				{
					head = head->next;
				}
				head->next = returnJob->next;
				returnJob->next = NULL;
				return returnJob;
			}
		}
	}
	else
	{
		return returnJob = NULL;
	}
	
}

void rrJobs(int timeSlice)
{//时间片轮转
	int currentTime = 0,timeControl=0;
	Job* runningJob = NULL;
	while (!is_empty(createdQueue) || !is_empty(readyQueue) || runningJob != NULL)
	{
		while (!is_empty(createdQueue))
		{
			
			Job* frontJob = peekQueue(createdQueue);
			if (frontJob->arriveTime == currentTime)
			{
				//后备出第一个挂入就绪队列
				enQueueNode(readyQueue, deQueue(createdQueue));

			}
			else {
				break;
			}
		}
		if (runningJob == NULL)
		{
			if (!is_empty(readyQueue))
			{
				runningJob = deQueue(readyQueue);
			}
			else
			{
				printf("系统%d时刻就绪队列为空\n", currentTime);
				currentTime++;
				continue;
			}
		}
		else
		{
			if (runningJob->usedTime == runningJob->requireTime)
			{
				runningJob->endedTime = currentTime;
				enQueueNode(endedQueue, runningJob);
				recordJobTime(runningJob);
				printf("作业%d已完成,完成时间:%d 等待时间%d\n", runningJob->PID, runningJob->endedTime,runningJob->waitedTime);

				if (!is_empty(readyQueue)) {
					runningJob = deQueue(readyQueue);
				}

				else {
					runningJob = NULL;
				}
			}
			
			else
			{

			}
		}
		currentTime++;
		
		
		if (runningJob != NULL)
		{
			
			runningJob->usedTime++;
			timeControl++;
			CacluateWaitedTime(readyQueue);
			if (timeControl == timeSlice)
			{//时间片到
				timeControl=0;

				while (!is_empty(createdQueue))
				{//先让后备队列进入就绪队列一个
					//返回队头作业
					Job* frontJob = peekQueue(createdQueue);
					if (frontJob->arriveTime == currentTime)
					{
						//后备出第一个挂入就绪队列
						enQueueNode(readyQueue, deQueue(createdQueue));

					}
					else {
						break;
					}
				}

				if (runningJob->usedTime != runningJob->requireTime)
				{//若当前作业还未完成
					printf("作业%d在%d时刻阻塞,剩余服务时间%d,等待时间%d\n", runningJob->PID
						, currentTime, runningJob->requireTime - runningJob->usedTime,runningJob->waitedTime);
					enQueueNode(readyQueue, runningJob);
					runningJob = NULL;
				}
				else {

				}
			}
		}
	}
	printf("rrJobs %d时间片 的调度信息:\n",timeSlice);
	printAvgValue();
}

void hrrnJobs()
{
	int currentTime = 0;
	Job* runningJob = NULL;
	
	
	while (!is_empty(createdQueue) || !is_empty(readyQueue) || runningJob != NULL)
	{
		while (!is_empty(createdQueue))
		{
			Job* frontJob = peekQueue(createdQueue);
			if (frontJob->arriveTime == currentTime)
			{
				enQueueNode(readyQueue, deQueue(createdQueue));
			}
			else
			{
				break;
			}
		}
		if (runningJob == NULL)
		{
			if (!is_empty(readyQueue))
			{
				runningJob = findHighestestJob(readyQueue);
			}
			else
			{
				printf("系统%d时刻就绪队列为空\n", currentTime);
				currentTime++;
				continue;
			}
		}
		else
		{
			if (runningJob->usedTime == runningJob->requireTime)
			{
				runningJob->endedTime = currentTime;
				enQueueNode(endedQueue, runningJob);
				recordJobTime(runningJob);
				printf("作业%d已完成, 完成时刻%d 等待时间%d\n", runningJob->PID, runningJob->endedTime
				                                               ,runningJob->waitedTime);

				if (!is_empty(readyQueue))
				{
					runningJob = findHighestestJob(readyQueue);

				}
				else
				{
					runningJob = NULL;

				}
			}
			else
			{
				//若当前作业还未完成,则什么都不做,在下面走一步

			}
		}
		currentTime++;
		
		if (runningJob != NULL)
		{
			CacluateWaitedTime(readyQueue);
			runningJob->usedTime++;
		}
	}
	printf("HRRNJobS调度信息:\n");
	printAvgValue();
}

Job* findHighestestJob(LinkedQueue* readyQueue)
{
	Job* returnJob = NULL, * head;
	head = readyQueue->front;
	if (readyQueue->front != NULL)
	{//就绪对列不为空
		if (head->next == NULL)
		{//若就绪队列只有一个
			returnJob = head;
			returnJob->next = NULL;
			readyQueue->front = readyQueue->rear = NULL;
			return returnJob;
		}
		else
		{//若队列中不止一个
			returnJob = head;
			while (head->next != NULL)
			{//循环整个就绪队列,记下最高相应比
				//计算相应比并且比较大小
				if ((float)(returnJob->waitedTime/returnJob->requireTime) <(float)(head->next->waitedTime/ head->next->requireTime))
				{
					returnJob = head->next;
					head = head->next;

				}
				else
				{
					head = head->next;
				}
			}
			head = readyQueue->front;

			if (head == returnJob)
			{//若返回的JOB是在队头
				head = head->next;
				//不要忘记变更就绪队列的队头!!!
				readyQueue->front = head;
				returnJob->next = NULL;
				return returnJob;


			}
			else
			{//返回的JOB不在队头
				while (head->next != returnJob)
				{
					head = head->next;
				}
				head->next = returnJob->next;
				returnJob->next = NULL;
				return returnJob;
			}
		}
	}
	else
	{
		return returnJob = NULL;
	}
}

void CacluateWaitedTime(LinkedQueue* queue)
{
	//iJob是用来循环就绪队列使等待时间++的控制变量赋予就绪队列的队头
	Job* iJob = queue->front;

	if (iJob != NULL)
	{//若就绪队列不为空
		while (iJob != NULL)
		{//循环队列增加作业的等待时间
			iJob->waitedTime++;

			iJob = iJob->next;
		}
		iJob = peekQueue(queue);
	}
}

你可能感兴趣的:(作业,操作系统,算法,c语言,编程语言)