- 动态优先级的时间片轮转调度算法
在多道程序运行环境下,进程数目一般多于处理机数目,使得进程要通过竞争来使用处理机。这就要求系统能按某种算法,动态地把处理机分配给就绪队列中的一个进程,使之运行,分配处理机的任务是由进程调度程序完成的。一个进程被创建后,系统为了便于对进程进行管理,将系统中的所有进程按其状态,将其组织成不同的进程队列。于是系统有运行进程队列、就绪进程队列和各种事件的进程等待队列。进程调度的功能就是从就绪队列中挑选一个进程到处理机上运行。进程调度的算法有多种,常用的有优先级调度算法、先来先服务算法、时间片轮转算法。
进程是程序在处理机上的执行过程。进程存在的标识是进程控制块(PCB),进程控制块参考结构如下:
typeedef struct node
{
char name[10]; /*进程标识符*/
int prio; /*进程优先数*/
int round; /*进程时间片轮转时间片*/
int cputime /*进程占用CPU时间*/
int neentime /*进程到完成还需要的时间*/
int count; /*计数器*/
char state; /*进程的状态*/
struct node *next; /*链指针*/
}PCB;
系统创建一个进程,就是由系统为某个程序设置一个PCB,用于对该进程进行控制和管理。进程任务完成,由系统收回其PCB,该进程便消亡。每个进程可以有三个状态:运行态、就绪态和完成状态。
- 使用优先数调度算法完成进程的调度
- 采用动态优先数法确定进程的优先级别。
- 设计三个链队列,分别用来表示运行队列、就绪队列和完成队列。
- 用户输入进程标识符以及进程所需要的时间,申请空间存放进程PCB信息。
优先数调度算法为每个进程设一个优先数,它总是把处理机给就绪队列中具有最高优先权的进程。常用的算法有静态优先数法和动态优先数法。
动态优先数法使进程的优先权随时间而改变。初始的进程优先数取决于进程运行所需要的时间,时间长则优先数低。可采取将进程优先数定为一个较大的数(比如50)减去进程运行所需要的时间。
随着进程的运行对优先数进行调整,每次运行时都是从就绪队列中选取优先数最大的进程运行。以一个时间片为固定周期T,每个周期动态调整各个进程的优先级,执行进程优先级降低(优先数减小),就绪进程优先级提升(优先数增加),每个时间片开始时,重新选择当前优先级最高的进程投入运行。如果进程所需时间为0,说明进程运行完毕,将其状态变为完成状态“F”,将此进程PCB插入到完成队列中,重复上述过程,直到就绪队列为空,所有进程都变为完成状态为止。
2.使用时间片轮转算法完成进程的调度
时间片轮转调度:具体做法是调度程序每次把CPU分配给当前最高优先级进程使用一个时间片。当这个时间片结束时,强迫该进程让出处理器,进行下一轮优先级调度,直至就绪队列中所有进程都运行完成为止。实现这种调度要使用一个间隔时钟。当一个进程开始运行时,就将时间片的值置入间隔时钟内,当发生间隔时钟中断时,就表明该进程连续运行的时间已超过一个规定的时间片。此时,中断处理程序就通知处理器调度进行处理器的切换工作。
- 使用优先数调度算法完成进程的调度
- 流程图
- 代码段
#include <stdio.h> #include <stdlib.h> #define CHOICE 50 /*用来初始化进程的优先级*/ typedef struct node { char name[10]; /*进程标识符*/ int prio; /*进程优先数*/ int round; /*进程时间片轮转时间片*/ int cputime; /*进程占用CPU时间*/ int needtime; /*进程到完成还需要的时间*/ int count; /*计数器*/ char state; /*进程的状态*/ struct node *next; /*链指针*/ } PCB, *Process; /*初始化PCB*/ Process initPCB(int time) { Process process = (Process)malloc(sizeof(PCB)); printf("请输入进程的标识符和运行所需时间\n"); scanf("%s %d", process->name, &(process->needtime)); process->cputime = 0; process->round = time; process->prio = CHOICE - process->needtime; process->state = 'R'; process->count = 0; process->next = NULL; return process; } // 初始化进程队列 Process initProcessQueue() { Process process = (Process)malloc(sizeof(PCB)); process->next = NULL; return process; } /*入队操作,按照优先级的大小来入队,类似于插入排序*/ void insertProcess(Process p, Process ready1) { Process ready = ready1; //如果就绪队列为空直接插入 if (!(ready->next)) { ready->next = p; } else { //遍历链表,并插入,temp用来记录是否插入队尾 int temp = 0; while (ready->next) { if (p->prio > ready->next->prio) { p->next = ready->next; ready->next = p; temp = 1; break; } else { ready = ready->next; } } //比所有的优先级都小,插入队尾 if (!temp) { ready->next = p; } } } /*出队操作,从首元结点开始出队*/ Process deleteProcess(Process p) { if (!p->next) { return p; } Process q = p->next; p->next = q->next; q->next = NULL; return q; } /*动态优先级增加,对队列中所有优先级动态增加*/ void addPriority(Process p, int priority) { Process q = p; while (q->next) { q->next->prio += priority; q = q->next; } } /*打印函数*/ void Output(Process p) { printf("%-10s", p->name); printf("%-10d", p->round); printf("%-10d", p->cputime); printf("%-10d", p->needtime); printf("%-10d", p->prio); printf("%-10c", p->state); printf("%-10d", p->count); printf("\n"); } /*打印函数*/ void Print(Process p) { if (!p->next) { printf("队列为空\n"); return; } printf("进程号 时间片 cpu时间 所需时间 优先数 状态 执行次数\n"); while (p->next) { Output(p->next); p = p->next; } } void runProcess(Process process) { /*运行进程,相应的参数改变*/ process->state = 'r'; process->needtime -= process->round; process->cputime += process->round; process->prio -= 5; //运行的进程优先级减5 process->count += 1; } int main() { int round; //时间片 printf("请输入时间片的大小\n"); scanf("%d", &round); /*创建就绪,运行,完成,3个队列*/ Process run = initProcessQueue(); Process ready = initProcessQueue(); Process finish = initProcessQueue(); /*创建进程,并初始化,加入就绪队列*/ printf("请输入你要创建的进程数量\n"); int count; //进程数 scanf("%d", &count); for (int i = 0; i < count; i++) { Process process = initPCB(round); insertProcess(process, ready); } /*运行状态,直到就绪队列为空,才停止*/ while (ready->next) { if (!run->next) { Process q = deleteProcess(ready); //就绪队列出队 insertProcess(q, run); //加入运行队列 runProcess(q); addPriority(ready, 2); //就绪队列中优先级加2 q = deleteProcess(run); //从运行队列出队 if (q->needtime <= 0) //判断运行时间是否小于0 { q->cputime += q->needtime; q->needtime = 0; q->state = 'F'; insertProcess(q, finish); //小于等于加入完成队列,并改变相应的参数 } else { q->state = 'R'; insertProcess(q, ready); //大于继续加入就绪队列 } } //每执行一次打印每个队列,观察执行情况 printf("************************************************************************"); printf("\n"); printf("完成队列:\n"); Print(finish); printf("\n"); printf("就绪队列:\n"); Print(ready); printf("\n"); printf("运行队列:\n"); Print(run); printf("\n"); } return 0; } /* Thans for Min! */
-
运行截图
-
注意至于代码中的优先级变换,可以自定义,优先级的变化,我的是执行优先级就要减5,没执行的都加2,其实就是相对差值的变换,根据自己的需要来调整,不是固定的,还有,这个实验的模拟的进程到达时间都是0,如果相应加一个到达时间,在PCB里添加一个相应的信息即可,在定义一个记录时间的全局变量,在判断一下,运用了数据结构中链表的知识,掌握一下链表的增加和删除就可写出这个模拟实验了,本次实验采用的c的代码,在cpp上可能会不兼容,以上代码均在vscode上跑过。
基于动态优先级的时间片轮转调度算法c语言
于 2021-05-09 13:58:10 首次发布