进程调度算法及实现

一、进程调度算法设计

设计进程调度算法时,需考虑以下问题:

  1. 引起调度时机
  • 正常结束或出现错误而异常结束
  • I/O请求,从运行状态进入阻塞状态
  • 正在运行执行某种原语操作进入阻塞状态,如P原语
  • 具有更高优先级的进程要求运行,则改进程进入就绪队列等待调用
  • 分配给该进程的时间片用完
  1. 进程调度方式
    进程调度方式有两种:
  • 非剥夺式调用
    当一个进程正在使用运行,若有一个更紧迫、重要(优先级更高)的进程到来,只能等到该进程主动退出运行状态,系统才能让更紧迫、重要的进程运行。
  • 剥夺式调用
    系统可以强制让正在运行进程退出运行状态,让更紧迫重要的进程运行。
  1. 调度算法选择
    分为两大类优先数法、时间片轮转法
    非剥夺式:先来先服务、短进程优先、高响应比优先、短剩余时间优先
    剥夺式:优先级调度、时间片轮转法、多级队列时间片轮转法
  2. 进程队列的组织
    进程队列的数据结构:
  • 线性表
  • 链表
    运行队列:一个队列,且最多只有一个进程运行
    就绪队列:一个队列,可以有多个进程
    阻塞队列:可以有多个,每个队列可以有多个进程

二、几种常用的算法的设计及实现

1. 进程优先

设计思想:采用非剥夺式调度,让运行时间短的进程先执行 特点:会出现进程运行时间长,而得不到调用出现饿死现象

2. 高响应比优先

设计思想:采用非剥夺式调用,让进程的(W)等待时间呵(R)运行时间之和除以它(R)运行时间的值(H)大的进程先得到调度,H=(W+R)/R可以近似看做H=W/R

特点:不会让进程饿死,运行时间也比较小,但是没考虑到重要进程的调度问题

3.动态优先级

设计思想:采用剥夺式调用,运行优先级数最大的进程,进程每得到一次调度它的优先级会减少一个值,运行完之后找出优先级最大的再次运行

特点:运行时间较中,但是短进程不能得到考虑

4. 动态优先级+时间片轮转

设计思想:采用剥夺式调用,按优先级一轮一轮的运行进程,进程每得到一次调度它的优先级会减少一个值,再执行下一个优先级次之的进程,

特点:这样可以是优先级数小的短进程得到调度,但是长进程调度运行次数较多,开销大造成资源浪费

5. 多级队列时间片轮转

设计思想:采用剥夺式调用,按时间片调度,进程每次运行完之后下次时间片分配更长

特点:使短进程的得到调用,长进程开销小,但是运行时间较长

6. 算法实现(C语言)

头文件PCB.h

包含进程队列及对进程队列操作

#include<stdio.h>
#include<malloc.h>

//PCB结构体
typedef struct {
	int ID;
	//进程优先数:PRIORITY(优先数越大,优先级越高)
	int PRIORITY;
	//进程已占用时间片:CPUTIME,每得到一次调度,值加1
	int CPUTIME;
	//进程剩余时间片:ALLTIME,每得到一次调度,该值减1,一旦运行完毕,ALLTIME为0
	int ALLTIME;
	//进程状态:
	int STATE;
	//等待时间
	int WAITTIME;
}PCB;

//进程队列信息
typedef struct Node {
	PCB pcb;
	//进程队列指针:NEXT,用来将PCB排成队列
	struct Node *next;
} PcbList;

int getPcbListSize(PcbList *pcb) {
	PcbList *p = pcb;
	int size = -1;
	while (p!=NULL) {
		size++;
		p = p->next;
	}
	return size;
}
//初始化队列
void init(PcbList **pcb) {
	*pcb = (PcbList*)malloc(sizeof(PcbList));
	(*pcb)->next = NULL;
}
//插入进程
void insertPCB(PcbList *pcb, int id, int priority, int cpuTime, int allTime) {
	PcbList *p, *q = pcb;
	p = (PcbList *)malloc(sizeof(PcbList));
	p->pcb.ID = id;
	p->pcb.PRIORITY = priority;
	p->pcb.CPUTIME = cpuTime;
	p->pcb.ALLTIME = allTime;
	p->pcb.WAITTIME = 0;
	p->next = NULL;
	p->pcb.STATE = 0;
	while (q != NULL && q->next != NULL) {
		q = q->next;
	}
	q->next = p;
}
// 删除结点
int deletePCB(PcbList *pcb, int id) {
	PcbList *p, *q = pcb;
	while (q != NULL) {
		if (q->next != NULL && q->next->pcb.ID == id) {
			p = q->next;
			q->next = q->next->next;
			free(p);
			return id;
		}
		q = q->next;
	}
	return -1;
}

// 打印队列所有信息
void PrintList(PcbList *pcb) {
	if (getPcbListSize<=0){
		return;
	}
	PcbList *p = pcb->next;
	printf("正在运行:\n");
	while (p != NULL) {
		if (p->pcb.STATE > 0) {
			printf("ID:%d\tPRIORITY:%d\tCPUTIME:%d\tALLTIME:%d\tWAITTIME:%d\tSTATE:running\n", p->pcb.ID, p->pcb.PRIORITY, p->pcb.CPUTIME, p->pcb.ALLTIME,p->pcb.WAITTIME);
		}
		p = p->next;
	}
	p = pcb->next;
	printf("就绪:\n");
	while (p != NULL) {
		if (p->pcb.STATE == 0) {
			printf("ID:%d\tPRIORITY:%d\tCPUTIME:%d\tALLTIME:%d\tWAITTIME:%d\tSTATE:ready\n", p->pcb.ID, p->pcb.PRIORITY, p->pcb.CPUTIME, p->pcb.ALLTIME, p->pcb.WAITTIME);
		}
		p = p->next;
	}
	printf("\n===========================================================================================\n");
}

//打印进程运行状态
void PrintPcbState(PcbList *pcb) {
	if (getPcbListSize <= 0) {
		return;
	}
	PcbList *p = pcb->next;
	printf("\t正在运行:\n\t");
	while (p != NULL) {
		if (p->pcb.STATE > 0) {
			printf("ID:%d\t", p->pcb.ID);
		}
		p = p->next;
	}
	p = pcb->next;
	printf("\n\t就绪:\n\t");
	while (p != NULL) {
		if (p->pcb.STATE == 0) {
			printf("ID:%d\t", p->pcb.ID);
		}
		p = p->next;
	}
	printf("\n\t======================================\n");
}

//交换p q的值
void swap(PcbList *p, PcbList *q) {
	PCB pcb;
	pcb.ID = p->pcb.ID;
	pcb.PRIORITY = p->pcb.PRIORITY;
	pcb.CPUTIME = p->pcb.CPUTIME;
	pcb.ALLTIME = p->pcb.ALLTIME;
	pcb.STATE = p->pcb.STATE;
	pcb.WAITTIME = p->pcb.WAITTIME;

	p->pcb.ID = q->pcb.ID;
	p->pcb.PRIORITY = q->pcb.PRIORITY;
	p->pcb.CPUTIME = q->pcb.CPUTIME;
	p->pcb.ALLTIME = q->pcb.ALLTIME;
	p->pcb.STATE = q->pcb.STATE;
	p->pcb.WAITTIME = q->pcb.WAITTIME;

	q->pcb.ID = pcb.ID;
	q->pcb.PRIORITY = pcb.PRIORITY;
	q->pcb.CPUTIME = pcb.CPUTIME;
	q->pcb.ALLTIME = pcb.ALLTIME;
	q->pcb.STATE = pcb.STATE;
	q->pcb.WAITTIME = pcb.WAITTIME;
}
// 按优先级对就绪队列排序 降序
void PcbListSortByPRIORITY(PcbList *pcb) {
	PcbList *p;
	int i, j;
	for (i = 0; i < getPcbListSize(pcb) - 1; i++) {
		p = pcb->next;
		for (j = 0; j < getPcbListSize(pcb) - 1 - i; j++, p = p->next) {
			if (p->pcb.PRIORITY < p->next->pcb.PRIORITY) {
				swap(p, p->next);
			}
		}
	}
}

// 按优先级对就绪队列排序 升序
void PcbListSortByPRIORITYAscend(PcbList *pcb) {
	PcbList *p;
	int i, j;
	for (i = 0; i < getPcbListSize(pcb) - 1; i++) {
		p = pcb->next;
		for (j = 0; j < getPcbListSize(pcb) - 1 - i; j++, p = p->next) {
			if (p->pcb.PRIORITY >= p->next->pcb.PRIORITY) {
				swap(p, p->next);
			}
		}
	}
}

// 按运行时间对就绪队列排序 升序
void PcbListSortByALLTIME(PcbList *pcb) {
	PcbList *p;
	int i, j;
	for (i = 0; i < getPcbListSize(pcb) - 1; i++) {
		p = pcb->next;
		for (j = 0; j < getPcbListSize(pcb) - 1 - i; j++, p = p->next) {
			if (p->pcb.ALLTIME > p->next->pcb.ALLTIME) {
				swap(p, p->next);
			}
		}
	}
}

头文件Run.h

短进程优先、高响应比优先、动态优先级、动态优先级+时间片轮转、多级队列时间片轮转的算法实现

#include"PCB.h"

//运行run进程times次,即时间片为times   prioritySub 为优先级减的数量
void running(PcbList *pcb, PcbList *run, int times, int prioritySub) {
	PcbList *p = pcb;
	for (int i = 0; i < times; i++) {
		run->pcb.PRIORITY -= prioritySub;	//优先级 -prioritySub
		run->pcb.CPUTIME += 1;				//在CPU运行时间 -1
		run->pcb.ALLTIME -= 1;				//剩余时间 -1
		run->pcb.STATE = 1;					//状态置为 running
		run->pcb.WAITTIME -= 1;				//等待时间 -1 **后面所有都要+1 所以等待时间不变
		p = pcb;
		//对就绪队列所有PCB等待时间+1
		while (p != NULL) {
			p->pcb.WAITTIME += 1;
			p = p->next;
		}
		//运行次数完退出
		if (run->pcb.ALLTIME <= 0) {
//			PrintPcbState(pcb);
			PrintList(pcb);
			run->pcb.STATE = 0;		//运行结束 状态置为就绪
			return;
		}
	}
//	PrintPcbState(pcb);
	PrintList(pcb);
	run->pcb.STATE = 0;		//运行结束 状态置为就绪
}

//动态优先队列
void startDynamicPriority(PcbList *pcb) {
	int count=0;				//运行时间片数
	int turnaroundTime = 0;		//周转时间
	while (getPcbListSize(pcb) > 0) {
		PcbListSortByPRIORITY(pcb);		//按优先级排序
		printf("第%d次运行:\n",++count);
		running(pcb, pcb->next, 3, 3);		//运行3次 每优先级-3
		if (pcb->next->pcb.ALLTIME<=0){		//运行时间用完 退出
			printf("\t*** %d 运行结束*** 周转时间%d\n", pcb->next->pcb.ID, pcb->next->pcb.WAITTIME + pcb->next->pcb.CPUTIME);
			turnaroundTime += pcb->next->pcb.WAITTIME + pcb->next->pcb.CPUTIME;		//保存周转时间
			deletePCB(pcb, pcb->next->pcb.ID);
		}
	}
	printf("运行完毕  总周转时间为:%d", turnaroundTime);
}

// 动态优先队列+时间片轮转
void startDPAndRR(PcbList *pcb) {
	PcbList *p,*q;
	int count = 0;						//运行时间片数
	int turnaroundTime = 0;				//周转时间
	while (getPcbListSize(pcb) > 0) {
		p = pcb->next;
		PcbListSortByPRIORITY(pcb);		//按优先级排序
		printf("第%d轮运行:\n", ++count);
		while(p!=NULL){					//运行一轮
			running(pcb, p, 3,3);		//运行1次 优先级-3
			q = p;
			p = p->next;
			if (q->pcb.ALLTIME <= 0) {
				printf("\t*** %d 运行结束*** 周转时间%d\n", q->pcb.ID, q->pcb.WAITTIME + q->pcb.CPUTIME);
				turnaroundTime += q->pcb.WAITTIME + q->pcb.CPUTIME;
				deletePCB(pcb, q->pcb.ID);
			}
		}
	}
	printf("运行完毕  总周转时间为:%d", turnaroundTime);
}


//多级时间片轮转
//将Priority改为多级轮转执行的次数
void startMultiLevelQueueRotation(PcbList *pcb) {
	PcbList *p, *q;
	p = pcb;
	while (p != NULL) {		//将所有PCB级数置为1
		p->pcb.PRIORITY = 1;
		p = p->next;
	}
	int count = 0;				//运行时间片数
	int turnaroundTime = 0;		//周转时间
	while (getPcbListSize(pcb) > 0) {
		PcbListSortByALLTIME(pcb);		//短进程优先
		p = pcb->next;
		printf("运行:\n");
		while (p != NULL) {
			p = pcb->next;
			PcbListSortByPRIORITYAscend(pcb);    //级数低在前面
			running(pcb, p, p->pcb.PRIORITY, 0); //执行 Priority 级次 PRIORITY不变
			p->pcb.PRIORITY *= 2;				// 执行次数每次*2
			q = p;
			p = p->next;
			if (q->pcb.ALLTIME <= 0) {

				printf("\t*** %d 运行结束*** 周转时间%d\n", q->pcb.ID, q->pcb.WAITTIME + q->pcb.CPUTIME);
				turnaroundTime += q->pcb.WAITTIME + q->pcb.CPUTIME;
				deletePCB(pcb, q->pcb.ID);
			}
		}
	}
	printf("运行完毕  总周转时间为:%d", turnaroundTime);
}

//高响应比优先
void startHighResponse(PcbList *pcb) {
	PcbList *p,*max;
	p = pcb;
	int count = 0;				//运行时间片数
	int turnaroundTime = 0;		//周转时间
	while (getPcbListSize(pcb) > 0) {
		p = pcb->next;
		max= p;
		while (p!=NULL){  //得到最大的响应比max
			if (max->pcb.WAITTIME*1.0 / max->pcb.ALLTIME < p->pcb.WAITTIME*1.0 / p->pcb.ALLTIME){
				max = p;
			}
			p = p->next;
		}
		printf("第%d次运行:\n", ++count);
		running(pcb, max, max->pcb.ALLTIME, 0);		//非剥夺式调用max运行直到ALLTIME为0
		if (max->pcb.ALLTIME <= 0) {
			printf("\t*** %d 运行结束*** 周转时间%d\n", max->pcb.ID, max->pcb.WAITTIME + max->pcb.CPUTIME);
			turnaroundTime += max->pcb.WAITTIME + max->pcb.CPUTIME;
			deletePCB(pcb, max->pcb.ID);
		}
		p = pcb->next;
		while (p != NULL) {
			p->pcb.PRIORITY++;
			p = p->next;
		}
	}
	printf("运行完毕  总周转时间为:%d",turnaroundTime);
}

//短进程优先
void startShortProcessPriority(PcbList *pcb) {
	PcbList *p = pcb;
	int count = 0;				//运行时间片数
	int turnaroundTime = 0;		//周转时间
	while (getPcbListSize(pcb) > 0) {
		PcbListSortByALLTIME(pcb);		//按剩余时间排序
		printf("第%d次运行:\n", ++count);
		running(pcb, pcb->next, pcb->next->pcb.ALLTIME, 0);	//非剥夺式调用pcb->next运行直到ALLTIME为0 优先级 -0
		if (pcb->next->pcb.ALLTIME <= 0) {
			printf("\t*** %d 运行结束*** 周转时间%d\n", pcb->next->pcb.ID, pcb->next->pcb.WAITTIME + pcb->next->pcb.CPUTIME);
			turnaroundTime += pcb->next->pcb.WAITTIME + pcb->next->pcb.CPUTIME;
			deletePCB(pcb, pcb->next->pcb.ID);
		}
	}
	printf("运行完毕  总周转时间为:%d", turnaroundTime);
}

测试函数:Main.c

测试这几种调度方法的算法

#include"Run.h"

int main() {
	PcbList *pcb;
	init(&pcb);
	insertPCB(pcb, 0, 9, 0, 3);
	insertPCB(pcb, 1, 38, 0, 2);
	insertPCB(pcb, 2, 30, 0, 6);
	insertPCB(pcb, 3, 29, 0, 3);
	insertPCB(pcb, 4, 0, 0, 4);
	PrintList(pcb);
//	startDynamicPriority(pcb);	//动态优先 总周转时间为:53
//	startDPAndRR(pcb);			//动态优先+时间片轮转 总周转时间为:56
//	startMultiLevelQueueRotation(pcb);	//多级时间片轮转 总周转时间为:66
//	startHighResponse(pcb);		//高响应比优先 总周转时间为:46
//	startShortProcessPriority(pcb);	//短进程优先 总周转时间为:45
	return 0;
}

测试结果:

动态优先:

java实现进程调度算法 进程调度算法的实现_进程调度

动态优先+时间片轮转:

java实现进程调度算法 进程调度算法的实现_进程调度_02


多级时间片轮转:

java实现进程调度算法 进程调度算法的实现_java实现进程调度算法_03


高响应比优先:

java实现进程调度算法 进程调度算法的实现_优先级_04


短进程优先

java实现进程调度算法 进程调度算法的实现_java实现进程调度算法_05