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