头歌实验4_进程调度算法

实验4_进程调度算法

第1关:链表操作

进程调度算法

进程并发时,有多个进程处于就绪队列,系统要从就绪队列中选择进程执行。系统选择方法包括:先来先服务,根据进程到达的先后顺序先到达的先执行。短作业优先:从就绪队列中选择服务时长最短的任先执行。时间片轮转:系统从就绪队列中选择队首进程执行,每次只执行一个时间片长,如果当前进程没有执行完毕,就将当前进程放入就绪队列尾。

进程调度算法针对就绪队列,涉及到排序,删除和添加等操作,这些操作比较适合用链表操作。本项目完成链表的创建和输出内容。

任务描述

本关任务:实现链表队列的初始化和输出。

相关知识

为了完成本关任务,你需要掌握:1.链表节点的添加2.链表节点的输出。

编程要求

根据提示,在右侧编辑器补充代码,分别实现链表节点的添加和节点信息的输出。

代码示例
//stu00.c 作业初始化及输出基本操作,程序模板,由学生完成缺失代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define TASK_COUNT 5
int iArrivePoint[TASK_COUNT] = { 0,1,2,3,4 };
int iTaskLen[TASK_COUNT] = { 4,3,5,2,4 };
char cPname[TASK_COUNT] = { 'A','B','C','D','E' };
//PCB节点链的定义
typedef struct _Pcb {
	int pid;      //进程ID
	int arriveP;  //到达时间点
	int taskLen;  //任务总时长
	int beginP;   //任务开始时间点
	int finishP;  //任务完成时间点
	int remains;  //未执行的时长
	char cPname;//进程名称
	int priority; //优先级
	struct _Pcb * next;
}PCB;

//初始化PCB队列
PCB* InitPcbQue()
{
	PCB* headOfPcb = NULL;
	PCB* curPcbNode;
	int i, indexP;
	//**************begin**********代码约十二行********/	
	//在循环结构中创建节点并加入到链表中 
	    for (i = 0; i < TASK_COUNT; i++)
	{
		curPcbNode = (PCB*)malloc(sizeof(PCB));
		//注意链表操作时最先入链的会排在最后。
		indexP = TASK_COUNT - i - 1;
		curPcbNode->pid = indexP;
		curPcbNode->arriveP = iArrivePoint[indexP];
		curPcbNode->taskLen = iTaskLen[indexP];
		curPcbNode->remains = iTaskLen[indexP];
		curPcbNode->cPname = cPname[indexP];
		curPcbNode->next = headOfPcb;
		headOfPcb = curPcbNode;
	}
	//***********************end*****************/ 
	return headOfPcb;
}
//输出链表信息
void PrintPcbQue(PCB* headPcb)
{
	PCB* curPcb;
	curPcb = headPcb;
	//不能直接使用headPcb节点输出,会改变链表结构
	//**************begin**********代码约五行********/	
	//在循环结构中输出节点信息  
while (curPcb != NULL)
	{
		printf("%C:%d,", curPcb->cPname, curPcb->taskLen);
		curPcb = curPcb->next;
	};
	//***********************end*****************/ 
    printf("\n");
	return;
}

//清空队列
void ClearPcbQue(PCB* headPcb)
{
	PCB* onePcb;
	//**************begin**********代码约五行********/	
	//在循环结构中释放节点内存  
while (headPcb != NULL)
	{
		onePcb = headPcb;
		headPcb = headPcb->next;
		free((void *)onePcb);
	}
	//***********************end*****************/ 
}

int main()
{
	PCB * pHead=NULL;
	pHead=InitPcbQue();
	PrintPcbQue(pHead); 
	ClearPcbQue(pHead); 
	return 0;
}
输出结果
A:4,B:3,C:5,D:2,E:4,

第2关:先来先服务进程调度

进程调度算法

进程并发时,有多个进程处于就绪队列,系统要从就绪队列中选择进程执行。系统选择方法包括:先来先服务,根据进程到达的先后顺序先到达的先执行。短作业优先:从就绪队列中选择服务时长最短的任先执行。时间片轮转:系统从就绪队列中选择队首进程执行,每次只执行一个时间片长,如果当前进程没有执行完毕,就将当前进程放入就绪队列尾。

任务描述

本关任务:编写模拟进程调度的先来先服务程序。

相关知识

为了完成本关任务,你需要掌握:1.理解FCFS调度算法原理2.链表实现队列操作。

FCFS先来先服务

先来先服务就是根据进程在系统中到达时间排序,先到的进程先执行。

周转时间,平均周转时间,带权周转时间
编程要求

根据提示,在右侧编辑器补充代码,计算先来先服务算法下进程的周转时间。

代码示例
//stu01.c FCFS进程调度算法,程序模板,由学生完成缺失代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define TASK_COUNT 5
int iArrivePoint[TASK_COUNT] = { 0,1,2,3,4 };
int iTaskLen[TASK_COUNT] = { 4,3,5,2,4 };
char cPname[TASK_COUNT] = { 'A','B','C','D','E' };


//PCB节点链的定义
typedef struct _Pcb {
	int pid;      //进程ID
	int arriveP;  //到达时间点
	int taskLen;  //任务总时长
	int beginP;   //任务开始时间点
	int finishP;  //任务完成时间点
	int remains;  //未执行的时长
	char cPname;//进程名称
	int priority; //优先级
	struct _Pcb * next;
}PCB;

//初始化PCB队列
PCB* InitPcbQue()
{
	PCB* headOfPcb = NULL;
	PCB* curPcbNode;
	int i, indexP;
	for (i = 0; i < TASK_COUNT; i++)
	{
		curPcbNode = (PCB*)malloc(sizeof(PCB));
		//注意链表操作时最先入链的会排在最后。
		indexP = TASK_COUNT - i - 1;
		curPcbNode->pid = indexP;
		curPcbNode->arriveP = iArrivePoint[indexP];
		curPcbNode->taskLen = iTaskLen[indexP];
		curPcbNode->remains = iTaskLen[indexP];
		curPcbNode->cPname = cPname[indexP];
		curPcbNode->next = headOfPcb;
        //curPcbNode->next = headOfPcb;
		headOfPcb = curPcbNode;
	}
	//printf("InitPcbQue finished.\n");
	return headOfPcb;
}
//输出链表信息
void PrintPcbQue(PCB* headPcb)
{
	PCB* curPcb;
	curPcb = headPcb;
	//不能直接使用headPcb节点输出,会改变链表结构
	while (curPcb != NULL)
	{
		printf("%C:%d,", curPcb->cPname, curPcb->finishP);
		curPcb = curPcb->next;
	};
	return;
}



//清空队列
void ClearPcbQue(PCB* headPcb)
{
	PCB* onePcb;
	while (headPcb != NULL)
	{
		onePcb = headPcb;
		headPcb = headPcb->next;
		free((void *)onePcb);
	}
}



PCB* headInitPcb; 
int FCFS()
{   //先来先服务
	//请在begin end语句间补全程序语句实现短作业优行算法调度进程 
	/*  begin *******************程序代码约11行******************************* */
	//对进程序列进行排序
	int totalTaskLen = 0;
	headInitPcb = InitPcbQue();
	PCB* itFCFSPcb = headInitPcb;
	/**************begin**********代码约七行*********/	
	//在循环结构中输出进程执行序列和完成时间  
  while(itFCFSPcb!=NULL)
	{
		totalTaskLen=totalTaskLen+itFCFSPcb->taskLen;
		itFCFSPcb->finishP=totalTaskLen;
		printf("%C:%d,",itFCFSPcb->cPname,itFCFSPcb->finishP);
		itFCFSPcb=itFCFSPcb->next;
	}
	/***********************end*****************/ 
	//清空短作业排序的PCB链表
	ClearPcbQue(headInitPcb);
	/*   end  ************************************************************** */
	//程序输出总周转时间(所有进程周转时间之和)
	return totalTaskLen;
}


int main()
{
	FCFS(); 
	return 0;
}
输出结果
A:4,B:7,C:12,D:14,E:18,

第3关:时间片轮转进程调度

任务描述

时间片轮转:系统从就绪队列中选择队首进程执行,每次只执行一个时间片长,如果当前进程没有执行完毕,就将当前进程放入就绪队列尾。

相关知识

为了完成本关任务,你需要掌握:1.理解时间片轮转调度算法原理2.链表实现队列操作。

模拟时间片算法描述

分时系统的调度方法,每个时间片的长度是固定长的,以轮转的方式依次分派给就绪队列中的进程,每个进程执行完一个时间片后就重新进入就绪队列的末尾等待下次时间片分派。有一种情况教材有遗漏,当一个时刻点即有新进程A到达,又刚刚一个进程B时间片结束,它们进入队列的顺序如何呢?根据教材提供的数据演示,按照新进程先入队,刚时间片结束的后入队的规则排列。 下面是教材中给出的演示示例。 运行演示

在该示例中,就绪队列是一个动态变化的队列,在每个时刻点队列中内容都会发生变化,每经过一个时间片,当前进程则减少一个时间值,如果没有结束,则从队列首移动到队列尾部。一个更清晰的示意图如下:

时间片1

在UBUNTU平台中,输出每个时刻的就绪队列: 就绪队列

该图也反映了进程的结束时间:B:10,D:11,A:12,E:17,C:18

编程要求

根据提示,在右侧编辑器补充代码,计算时间片轮转算法下进程的结束时间。

代码示例
//as02.c RoundRobin进程调度算法,程序模板,由学生完成缺失代码
//输出:B:10,D:11,A:12,E:17,C:18, 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define TASK_COUNT 5
int iArrivePoint[TASK_COUNT] = { 0,1,2,3,4 };
int iTaskLen[TASK_COUNT] = { 4,3,5,2,4 };
char cPname[TASK_COUNT] = { 'A','B','C','D','E' };
//PCB节点链的定义
typedef struct _Pcb {
	int pid;      //进程ID
	int arriveP;  //到达时间点
	int taskLen;  //任务总时长
	int beginP;   //任务开始时间点
	int finishP;  //任务完成时间点
	int remains;  //未执行的时长
	char cPname;//进程名称
	int priority; //优先级
	struct _Pcb* next;
}PCB;
 
//初始化PCB队列
PCB* InitPcbQue()
{
	PCB* headOfPcb = NULL;
	PCB* curPcbNode;
	int i, indexP;
	for (i = 0; i < TASK_COUNT; i++)
	{
		curPcbNode = (PCB*)malloc(sizeof(PCB));
		//注意链表操作时最先入链的会排在最后。
		indexP = TASK_COUNT - i - 1;
		curPcbNode->pid = indexP;
		curPcbNode->arriveP = iArrivePoint[indexP];
		curPcbNode->taskLen = iTaskLen[indexP];
		curPcbNode->remains = iTaskLen[indexP];
		curPcbNode->cPname = cPname[indexP];
		curPcbNode->next = headOfPcb;
		headOfPcb = curPcbNode;
	}
	//printf("InitPcbQue finished.\n");
	return headOfPcb;
}
//输出链表信息
void PrintPcbQue(PCB* headPcb)
{
	PCB* curPcb;
	curPcb = headPcb;
	//不能直接使用headPcb节点输出,会改变链表结构
	while (curPcb != NULL)
	{
		//		printf("%C:%d,", curPcb->cPname, curPcb->finishP);
		printf("%C,", curPcb->cPname);
		curPcb = curPcb->next;
	}
	printf("\n");
	return;
}
 
 
//清空队列
void ClearPcbQue(PCB* headPcb)
{
	PCB* onePcb;
	while (headPcb != NULL)
	{
		onePcb = headPcb;
		headPcb = headPcb->next;
		free((void*)onePcb);
	}
}
 
 
 
PCB* headInitPcb;
PCB* RRHeadP = NULL;//就绪队列头指针
PCB* RRRearP = NULL;//就绪队列尾指针
PCB* finishHead = NULL;//完成的进程节点
PCB* finishRear = NULL;//完成的进程节点
//将新进程PCB节点移到队尾
void AddNewToRear(PCB* newNode)
{
	RRRearP->next = newNode;
	RRRearP = newNode;
}
 
//将完成任务的节点加到完成进程队尾
void AddToFinishQ(PCB* newNode)
{
	PCB* onePcb;
	if (finishHead == NULL)
	{
		finishHead = (PCB*)malloc(sizeof(PCB));
		memcpy((void*)finishHead, (void*)newNode, sizeof(PCB));
		finishHead->next = NULL;
		finishRear = finishHead;
	}
	else {
		onePcb = (PCB*)malloc(sizeof(PCB));
		memcpy((void*)onePcb, (void*)newNode, sizeof(PCB));
		onePcb->next = NULL;
		finishRear->next = onePcb;
		finishRear = onePcb;
	}
}
 
 
//执行一个时间片,从就绪队列首执行进程一个时间片,
//该结点PCB剩余时长减一,然后后移到队尾
int TimeSliceGo(int iTimeNum)
{
	int iRet = -1;
	PCB* oneNode;
	PCB* twoNode;
 
	//首个进程PCB递减一个数值
	RRHeadP->remains--;
	if (RRHeadP->remains == 0)
	{//当前进程执行完毕
		RRHeadP->finishP = iTimeNum;
		//进程执行完当前PCB进入完成队列
		AddToFinishQ(RRHeadP);
		//1.执行完全部进程
		if (RRHeadP == RRRearP)
		{//全部运行结束
			iRet = 0;
		}
		else {
			//删除队首pcb
			twoNode = RRHeadP;
			oneNode = RRHeadP->next;
			RRHeadP = oneNode;
			free((void*)twoNode);
		}
	}
	else {//当前节点进入队列尾部
		if (RRHeadP == RRRearP)
		{//只有一个节点啥也不做			
		}
		else {
			oneNode = RRHeadP->next;
			RRRearP->next = RRHeadP;
			RRRearP = RRRearP->next;
			RRRearP->next = NULL;
			RRHeadP = oneNode;
		}
	}
	return iRet;
}
 
 
//时间片轮转调度算法,实现方法1
int RoundRobin()
{ //时间片轮转法,在同一时刻,新建进程先入队列尾,刚结束的进程后入队尾
	PCB* headPcb = NULL;
	PCB* oldNode = NULL;//指向旧节点队列
	PCB* newNode = NULL;//指向新节点队列 
	PCB* oneNode = NULL;
	PCB* itOldPcb = NULL;
 
	//请在begin end语句间补全程序语句实现时间片轮转算法调度进程 
	/*  begin ************************************************** */
	//对进程序列进行排序
	//得到原始的进程任务列表
	headInitPcb = InitPcbQue();
	itOldPcb = headInitPcb->next;
	//初始化就绪进程队列
	RRHeadP = (PCB*)malloc(sizeof(PCB));
	memcpy((void*)RRHeadP, (void*)headInitPcb, sizeof(PCB));
	RRHeadP->next = NULL;
	RRRearP = RRHeadP;
 
	int iGoValue = 1, timeNum = 1;
 
	while (iGoValue != 0)
	{
		if (itOldPcb != NULL)
		{
			if (itOldPcb->arriveP == timeNum)
			{
				oneNode = (PCB*)malloc(sizeof(PCB));
				memcpy((void*)oneNode, (void*)itOldPcb, sizeof(PCB));
				oneNode->next = NULL;
				AddNewToRear(oneNode);
				itOldPcb = itOldPcb->next;
			}
		}
		//检查
		//j是时间片编号
		iGoValue = TimeSliceGo(timeNum);
		//printf("timeNum=%d,", timeNum);
		//PrintPcbQue(RRHeadP);
		timeNum++;
	}
 
	//计算每个进程的周转时间
	int iTotal = 0;
	oneNode = finishHead;
	while (oneNode != NULL)
	{
		//周转时间=结束时间-到达时间 
		iTotal += oneNode->finishP - oneNode->arriveP;
		printf("%c:%d ", oneNode->cPname, oneNode->finishP - oneNode->arriveP);
		oneNode = oneNode->next;
	}
	//printf("    iTotal:%d\n", iTotal);
	/*   end  ************************************************************** */
	//程序输出总周转时间(所有进程周转时间之和)
	return 0;
}
 
int main()
{
	RoundRobin();
	return 0;
}
 
 
 
//到达进程队列
PCB* arrivePcbQue = NULL;
//当前到达进程
PCB* curarrivePcb = NULL;
//执行进程队列
PCB* exePcbQue = NULL;
//执行进程队尾
PCB* exePcbQueTail = NULL;
//当前执行时间
int curExeTime = 0;
//时间片大小
int RRTimeSlice = 1;
int RRTimeSliceRemains = 0;
//调度执行进程exePcbQue一个时间片RRTimeSlice,
//如果完毕释放,调度下一个。
//将当前调度的进程剩余的时间RRTimeSliceRemains传递给下一个调度的进程。
//如果没有执行完毕,则将该执行进程放到执行队列尾。
void exeRRPcb()//int &RRTimeSliceRemains)
{
	PCB* exePcbHead = exePcbQue;
	int remainsTime = exePcbHead->remains - RRTimeSlice - RRTimeSliceRemains;
	if (exePcbHead->taskLen == exePcbHead->remains)//如果是第一次执行
		exePcbHead->beginP = curExeTime;
 
	//如果执行完毕,则释放
	if (remainsTime <= 0)
	{
		/*  begin ************************************************** */
		curExeTime += exePcbHead->remains;
		exePcbHead->finishP = curExeTime;
		printf("%C:%d,", exePcbHead->cPname, exePcbHead->finishP);// -exePcbHead->arriveP);
		RRTimeSliceRemains -= remainsTime;
		exePcbQue = exePcbQue->next;
		/*   end  ************************************************************** */
		free((void*)exePcbHead);
	}
	//否则放到执行进程队列队尾
	else
	{
		/*  begin ************************************************** */
		exePcbHead->remains -= RRTimeSlice;
		curExeTime += RRTimeSlice;
		exePcbQueTail->next = exePcbHead;
		exePcbQueTail = exePcbHead;
		exePcbQue = exePcbQue->next;
		exePcbQueTail->next = NULL;
		RRTimeSliceRemains = 0;
		/*   end  ************************************************************** */
	}
}
 
//将从当前到达进程curarrivePcb开始,
//到达时间<= curExeTime + RRTimeSlice的进程插入到执行进程尾。
void InsertRRexePcbQueTail()
{
	while (curarrivePcb != NULL && curarrivePcb->arriveP <= (curExeTime + RRTimeSlice))
	{
		/*  begin ************************************************** */
		exePcbQueTail->next = curarrivePcb;
		exePcbQueTail = curarrivePcb;
		curarrivePcb = curarrivePcb->next;
		exePcbQueTail->next = NULL;
		/*   end  ************************************************************** */
	}
}
void InsertRRexePcbQueHead()
{
	while (curarrivePcb != NULL && curarrivePcb->arriveP <= (curExeTime))// +RRTimeSlice))
	{
		PCB* tempPcb = curarrivePcb;
		curarrivePcb = curarrivePcb->next;
		tempPcb->next = exePcbQue;
		exePcbQue = tempPcb;
	}
}
//时间片轮转调度算法,实现方法2
void RR()
{
	while (exePcbQue != NULL)
	{
		/*  begin ************************************************** */
		InsertRRexePcbQueTail();
		exeRRPcb();
		//		InsertRRexePcbQueHead();
		//		PrintPcbQue(exePcbQue);
			/*   end  ************************************************************** */
	}
}
 
 
/*int main()
{
	//得到原始的到达的进程任务列表
	arrivePcbQue = InitPcbQue();
	exePcbQue = arrivePcbQue;
	exePcbQueTail = exePcbQue;
	curarrivePcb = arrivePcbQue->next;
	exePcbQueTail->next = NULL;
	RR();
	return 0;
}
*/
输出结果
B:9 D:8 A:12 E:13 C:16

第4关:短作业优先调度算法

任务描述

短作业优先:从就绪队列中选择服务时长最短的任先执行。

相关知识

为了完成本关任务,你需要掌握:1.理解SJF调度算法原理2.链表实现队列操作(排序,增,删)。

SJF短作业优先

短作业优先算法是对当前就绪队列的服务时间进行排序,选择最短时间的进程先执行。程序首先使用链表创建一个原始的进程序列,开始调用SJF算法时,就绪队列中只有第一个pcb,然后计算进程的完成时间,从原始进程序列中查看所有小于等于当前完成时间点的进程,加入到就绪队列中。对就绪对列中所有进程任务时长进行排序,短任务的排在最前,选队首的作为执行的pcb,并登记执行pcb到完成序列中。继续进行下次循环,直到所有进程执行完毕。最后输出进程的代号和完成时间。

编程要求

根据提示,在右侧编辑器补充代码,计算短作业优先算法下进程的结束时间。

代码示例
//输出:A:4,D:6,B:9,E:13,C:18,
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define TASK_COUNT 5
int iArrivePoint[TASK_COUNT] = { 0,1,2,3,4 };
int iTaskLen[TASK_COUNT] = { 4,3,5,2,4 };
char cPname[TASK_COUNT] = { 'A','B','C','D','E' };
//PCB节点链的定义
typedef struct _Pcb {
	int pid;      //进程ID
	int arriveP;  //到达时间点
	int taskLen;  //任务总时长
	int beginP;   //任务开始时间点
	int finishP;  //任务完成时间点
	int remains;  //未执行的时长
	char cPname;//进程名称
	int priority; //优先级
	struct _Pcb * next;
}PCB;
 
//初始化PCB队列
PCB* InitPcbQue()
{
	PCB* headOfPcb = NULL;
	PCB* curPcbNode;
	int i, indexP;
	for (i = 0; i < TASK_COUNT; i++)
	{
		curPcbNode = (PCB*)malloc(sizeof(PCB));
		//注意链表操作时最先入链的会排在最后。
		indexP = TASK_COUNT - i - 1;
		curPcbNode->pid = indexP;
		curPcbNode->arriveP = iArrivePoint[indexP];
		curPcbNode->taskLen = iTaskLen[indexP];
		curPcbNode->remains = iTaskLen[indexP];
		curPcbNode->cPname = cPname[indexP];
		curPcbNode->next = headOfPcb;
		headOfPcb = curPcbNode;
	}
	return headOfPcb;
}
//输出链表信息
void PrintPcbQue(PCB* headPcb)
{
	PCB* curPcb;
	curPcb = headPcb;
	//不能直接使用headPcb节点输出,会改变链表结构
	while (curPcb != NULL)
	{
		printf("%C:%d,", curPcb->cPname, curPcb->finishP);
		curPcb = curPcb->next;
	}
	printf("\n");
	return;
}
 
//清空队列
void ClearPcbQue(PCB* headPcb)
{
	PCB* onePcb;
	while (headPcb != NULL)
	{
		onePcb = headPcb;
		headPcb = headPcb->next;
		free((void *)onePcb);
	}
}
 
//对旧链表进行排序,生成短作业在前的新PCB队列
PCB* BuildSortedPcbSF(PCB* theOldHead)
{
	PCB * headPcb = NULL;
	PCB * oldNode = NULL;//指向旧节点队列
	PCB * newNode = NULL;//指向新节点队列
	PCB *oneNode = NULL;
	//复制头节点
	headPcb = (PCB *)malloc(sizeof(PCB));
	memcpy((void*)headPcb, (void*)theOldHead, sizeof(PCB));
	headPcb->next = NULL;
	oldNode = theOldHead->next;
	newNode = headPcb;
	/*  begin ***********代码约三十行************************************* */
	//生成短作业在前的新PCB队列
	while (oldNode != NULL)
	{
		//当前节点任务时长比头节点小,则插入头节点前
		if ((oldNode->taskLen) < (headPcb->taskLen))
		{
			newNode = (PCB *)malloc(sizeof(PCB));
			memcpy((void*)newNode, (void*)oldNode, sizeof(PCB));
			newNode->next = headPcb;
			headPcb = newNode;
			oldNode = oldNode->next;
			continue;
		}
		//从新队列首进行查找合适的位置
		newNode = headPcb;
		while (newNode->next != NULL)
		{
			if ((oldNode->taskLen) >= (newNode->next->taskLen))
			{
				newNode = newNode->next;
				continue;
			}
			if ((oldNode->taskLen) < (newNode->next->taskLen))
			{
				oneNode = (PCB *)malloc(sizeof(PCB));
				memcpy((void*)oneNode, (void*)oldNode, sizeof(PCB));
				oneNode->next = newNode->next;
				newNode->next = oneNode;
				//插入成功后,节点要后移。
				oldNode = oldNode->next;
				break;
			}
		}
		if (newNode->next == NULL)
		{
			oneNode = (PCB *)malloc(sizeof(PCB));
			memcpy((void*)oneNode, (void*)oldNode, sizeof(PCB));
			oneNode->next = NULL;
			newNode->next = oneNode;
			oldNode = oldNode->next;
			continue;
		}
	}
	/*   end  ************************************************************** */
	//清除旧pcb链表
	ClearPcbQue(theOldHead);
	return headPcb;
}
 
PCB* headInitPcb;
int SJF()
{ //短作业优先 
	PCB* headSFPcb;
	PCB* newNode;
	PCB* itComePcb = NULL;//任务到达的进程列表
	PCB* itSFPcb = NULL;
	PCB* readyPcb = NULL;//当前就绪队列
 
	//得到原始的进程任务列表
	headInitPcb = InitPcbQue();
	itComePcb = headInitPcb->next;
	//计算每个PCB的周转时长
	int totalTaskLen = 0;
	int i = 0;
	int j = 0;
	//就绪队列开始只有一个就绪进程
	readyPcb = (PCB *)malloc(sizeof(PCB));
	memcpy((void*)readyPcb, (void*)headInitPcb, sizeof(PCB));
	readyPcb->next = NULL;
 
 
	PCB* finishHead = NULL;//完成的进程节点
	PCB* finishRear = NULL;//完成的进程节点
 
	int iStartP = 0, iFinishedP = 0;
	/*  begin ***********代码约三十行************************************* */
	//请在begin end语句间补全程序语句实现短作业优先算法调度进程
	while (readyPcb != NULL)
	{
		//1.从ready队列将首个PCB移到完成队列中
		if (finishHead == NULL)
		{
			finishHead = readyPcb;
			newNode = readyPcb->next;
			finishHead->next = NULL;
			finishRear = finishHead;
			readyPcb = newNode;
		}
		else
		{
			finishRear->next = readyPcb;
			newNode = readyPcb->next;
			//队尾指针后移一个
			finishRear = finishRear->next;
			finishRear->next = NULL;
			readyPcb = newNode;
		}
		//计算当前进程结束时间点
		iFinishedP = iFinishedP + finishRear->taskLen;
		finishRear->finishP = iFinishedP;
 
 
		//2.处理就绪队列
		//查看原始队列是否为空
		int iAddNewPcb = 0;
		while (itComePcb != NULL)
		{ //从到达进程队列里查找所有早于刚完成的任务时间点,加入就绪队列中
			if (itComePcb->arriveP <= iFinishedP)
			{
				//新节点暂时放队首没问题,后面会排序
				newNode = (PCB *)malloc(sizeof(PCB));
				memcpy((void*)newNode, (void*)itComePcb, sizeof(PCB));
				newNode->next = readyPcb;
				readyPcb = newNode;
				//遍历原始进程队列
				itComePcb = itComePcb->next;
				//就绪队列中添加了新进PCB
				iAddNewPcb = 1;
			}
		}
		if (iAddNewPcb)
		{
			//对当前就绪进程队列按任务时长进行排序,短任务在前
			readyPcb = BuildSortedPcbSF(readyPcb);
		} 
	}
	/*   end  ************************************************************** */
	PrintPcbQue(finishHead);
	//清空短作业排序的PCB链表
	ClearPcbQue(finishHead);
	return totalTaskLen;
}
 
/*
int main()
{
	SJF();
	return 0;
}
*/
 
//调度执行进程exePcb,完毕释放。
void exeSJPcb(PCB *exePcb)
{
	/*  begin ************************************************************** */
	exePcb->finishP = exePcb->beginP + exePcb->taskLen;
	/*   end  ************************************************************** */
	printf("%C:%d,", exePcb->cPname, exePcb->finishP);
	free((void *)exePcb);
}
 
PCB *arrivePcbQue = NULL;
//从到达进程队列arrivePcbQue中找到当前执行进程执行完之前exePcbfinishP
//到达进程队列arrivePcbQue中任务时间最短的进程SJPcb返回并从到达进程队列中删除该结点。
PCB* FindSJPcb(int exePcbfinishP)
{
	//假设就绪队列的第一个节点就是最短进程
	PCB *SJPcb = arrivePcbQue;
	PCB *SJPrePcb = NULL;
	PCB *curPcb = arrivePcbQue;
	PCB *curPrePcb = NULL;
	while(curPcb != NULL && curPcb->arriveP <= exePcbfinishP)
	{
		if(curPcb->taskLen < SJPcb->taskLen)
		{
	/*  begin ************************************************************** */
			SJPrePcb = curPrePcb;
			SJPcb = curPcb;
	/*   end  ************************************************************** */
		}
		curPrePcb = curPcb;
		curPcb = curPcb->next;
	}
	if(SJPrePcb == NULL)
	{
	/*  begin ************************************************************** */
		arrivePcbQue = SJPcb->next;
	/*   end  ************************************************************** */
	}
	else
	{
	/*  begin ************************************************************** */
		SJPrePcb->next = SJPcb->next;
	/*   end  ************************************************************** */
	}
	return SJPcb;
 
}
 
//对到达的进程队列进行最短进程调度,算法2
void SJF1()
{
	//总是执行到达队列的第一个进程
	int exePcbfinishP = 0;
	while(arrivePcbQue != NULL)
	{
	/*  begin ************************************************************** */
		PCB* SJPcb = FindSJPcb(exePcbfinishP);
		SJPcb->beginP = exePcbfinishP;
		exePcbfinishP = SJPcb->beginP + SJPcb->taskLen;
		exeSJPcb(SJPcb);
	/*   end  ************************************************************** */
	}
}
 
 
int main()
{
	arrivePcbQue = InitPcbQue();
	SJF1();
	return 0;
}
输出结果
A:4,D:6,B:9,E:13,C:18,

恭喜你,闯关成功!

  • 3
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值