zoukankan      html  css  js  c++  java
  • 多级反馈队列调度算法

     

     

     

    实 验 报 告(拓展实验1)

    多级反馈队列调度算法

     

     

    课程名称 操作系统实验

    学生学院 计算机学院

    专业班级 17网络工程一班

    学 号 31170050**

    学生姓名 陈鸿

    指导教师 林穗

     

     

     

     

     

    2019 12 6

     

    目录

    一、    实验目的    3

    二、实验内容    3

    多级反馈队列调度算法的概念:    3

    应用范围:    3

    三、实现思路    4

    四、主要的数据结构    4

    void Output(); /*进程信息输出函数*/    5

    void InsertFinish(PCB *in); /*将进程插入到完成队列尾部*/    5

    void InsertPrio(ReadyQueue *in); /*创建就绪队列,规定优先数越小,优先级越低*/    5

    void PrioCreate(); /*创建就绪队列输入函数*/    5

    void GetFirst(ReadyQueue *queue); /*取得某一个就绪队列中的队头进程*/    5

    void InsertLast(PCB *in,ReadyQueue *queue); /*将进程插入到就绪队列尾部*/    5

    void ProcessCreate(); /*进程创建函数*/    5

    void RoundRun(ReadyQueue *timechip); /*时间片轮转调度算法*/    5

    void MultiDispatch(); /*多级调度算法,每次执行一个时间片*/    5

    int main(void)    6

    五、算法流程图    12

    六、运行与测试    12

    用例描述:    12

    运行截图:    13

    七、总结    13

     

     

     

     

     

     

     

     

     

     

    Tips:建议打开word【导航视图】与【批注】阅读。

     

    拓展实验1:多级反馈队列调度算法

    1. 实验目的

    分析操作系统的核心功能模块,理解相关功能模块实现的数据结构和算法,并加以实现,加深对操作系统原理和实现过程的理解。本次实验: 分析并实现多级反馈队列调度算法的模拟。

     

    二、实验内容

    多级反馈队列调度算法的概念:

    是一种根据先来先服务原则给就绪队列排序,为就绪队列赋予不同的优先级数,不同的时间片,按照优先级抢占CPU的调度算法。算法的实施过程如下:

     

    (1)按照先来先服务原则排序,设置N个就绪队列为Q1,Q2...QN,每个队列中都可以放很多作业;

    (2)为这N个就绪队列赋予不同的优先级,第一个队列的优先级最高,第二个队列次之,其余各队列的优先权逐个降低;

    (3)设置每个就绪队列的时间片,优先权越高,算法赋予队列的时间片越小。时间片大小的设定按照实际作业(进程)的需要调整;

    (4)进程在进入待调度的队列等待时,首先进入优先级最高的Q1等待。

    (5)首先调度优先级高的队列中的进程。若高优先级中队列中已没有调度的进程,则调度次优先级队列中的进程。例如:Q1,Q2,Q3三个队列,只有在Q1中没有进程等待时才去调度Q2,同理,只有Q1,Q2都为空时才会去调度Q3。

    (6)对于同一个队列中的各个进程,按照时间片轮转法调度。比如Q1队列的时间片为N,那么Q1中的作业在经历了时间片为N的时间后,若还没有完成,则进入Q2队列等待,若Q2的时间片用完后作业还不能完成,一直进入下一级队列,直至完成。

    (7)在低优先级的队列中的进程在运行时,又有新到达的作业,那么在运行完这个时间片后,CPU马上分配给新到达的作业即抢占式调度CPU。

     

    应用范围:

    此算法应用于同一个资源的多个使用者可分优先级使用资源的情况。

    三、实现思路

    1、设置多个就绪队列,并给队列赋予不同的优先级数,第一个最高,依次递减。

     

    2、赋予各个队列中进程执行时间片的大小,优先级越高的队列,时间片越小。

     

    3、当一个新进程进入内存后,首先将其放入一个对列末尾,如果在一个时间片

    结束时尚未完成,将其转入第二队列末尾。

     

    4、当一个进程从一个对列移至第n个队列后,便在第n个队列中采用时间片轮转执行完。

     

    5、仅当时间片空闲时,才调度第二个队列中的进程。

    (1~i-1)空闲时,才调度i,如果处理机正在第i队列中运行,又有新进程进入优先权较高

    队列,则新进程抢占处理机,将正在运行的进程放入第i队列队尾,将处理机分给新进程。

     

    四、主要的数据结构

    #include <stdio.h>

    #include <stdlib.h>

    #include <string.h>

    typedef struct node /*进程节点信息*/

    {

    char name[20]; /*进程的名字*/

    int prio; /*进程的优先级*/

    int round; /*分配CPU的时间片*/

    int cputime; /*CPU执行时间*/

    int needtime; /*进程执行所需要的时间*/

    char state; /*进程的状态,W--就绪态,R--执行态,F--完成态*/

    int count; /*记录执行的次数*/

    struct node *next; /*链表指针*/

    }PCB;

    typedef struct Queue /*多级就绪队列节点信息*/

    {

    PCB *LinkPCB; /*就绪队列中的进程队列指针*/

    int prio; /*本就绪队列的优先级*/

    int round; /*本就绪队列所分配的时间片*/

    struct Queue *next; /*指向下一个就绪队列的链表指针*/

    }ReadyQueue;

    PCB *run=NULL,*finish=NULL; /*定义三个队列,就绪队列,执行队列和完成队列*/

    ReadyQueue *Head = NULL; /*定义第一个就绪队列*/

    int num; /*进程个数*/

    int ReadyNum; /*就绪队列个数*/

     

    void Output(); /*进程信息输出函数*/

    void InsertFinish(PCB *in); /*将进程插入到完成队列尾部*/

    void InsertPrio(ReadyQueue *in); /*创建就绪队列,规定优先数越小,优先级越低*/

    void PrioCreate(); /*创建就绪队列输入函数*/

    void GetFirst(ReadyQueue *queue); /*取得某一个就绪队列中的队头进程*/

    void InsertLast(PCB *in,ReadyQueue *queue); /*将进程插入到就绪队列尾部*/

    void ProcessCreate(); /*进程创建函数*/

    void RoundRun(ReadyQueue *timechip); /*时间片轮转调度算法*/

    void MultiDispatch(); /*多级调度算法,每次执行一个时间片*/

     

     

    int main(void)

    {

    PrioCreate(); /*创建就绪队列*/

    ProcessCreate();/*创建就绪进程队列*/

    MultiDispatch();/*算法开始*/

    Output(); /*输出最终的调度序列*/

    return 0;

    }

    void Output() /*进程信息输出函数*/

    {

    ReadyQueue *print = Head;

    PCB *p;

    printf("进程名 优先级 轮数 cpu时间 需要时间 进程状态 计数器 ");

    while(print)

    {

    if(print ->LinkPCB != NULL)

    {

    p=print ->LinkPCB;

    while(p)

    {

    printf("%s %d %d %d %d %c %d ",p->name,p->prio,p->round,p->cputime,p->needtime,p->state,p->count);

    p = p->next;

                     }

             }

    print = print->next;

         }

    p = finish;

    while(p!=NULL)

    {

    printf("%s %d %d %d %d %c %d ",p->name,p->prio,p->round,p->cputime,p->needtime,p->state,p->count);

    p = p->next;

    }

    p = run;

    while(p!=NULL)

    {

    printf("%s %d %d %d %d %c %d ",p->name,p->prio,p->round,p->cputime,p->needtime,p->state,p->count);

    p = p->next;

    }

    }

    void InsertFinish(PCB *in) /*将进程插入到完成队列尾部*/ {

    PCB *fst;

    fst = finish;

    if(finish == NULL)

    {

    in->next = finish;

    finish = in;

    }

    else

    {

    while(fst->next != NULL)

    {

    fst = fst->next;

             }

    in ->next = fst ->next;

    fst ->next = in;

    }

    }

    void InsertPrio(ReadyQueue *in) /*创建就绪队列,规定优先数越小,优先级越低*/

    {

    ReadyQueue *fst,*nxt;

    fst = nxt = Head;

    if(Head == NULL) /*如果没有队列,则为第一个元素*/

    {

    in->next = Head;

    Head = in;

    }

    else /*查到合适的位置进行插入*/

    {

    if(in ->prio >= fst ->prio) /*比第一个还要大,则插入到队头*/

    {

    in->next = Head;

    Head = in;

    }

    else

    {

    while(fst->next != NULL) /*移动指针查找第一个别它小的元素的位置进行插入*/

    {

    nxt = fst;

    fst = fst->next;

                     }

    if(fst ->next == NULL) /*已经搜索到队尾,则其优先级数最小,将其插入到队尾即可*/

    {

    in ->next = fst ->next;

    fst ->next = in;

    }

    else /*插入到队列中*/

    {

    nxt = in;

    in ->next = fst;

    }

    }

    }

    }

    void PrioCreate() /*创建就绪队列输入函数*/

    {

    ReadyQueue *tmp;

    int i;

    printf("输入就绪队列的个数: ");

    scanf("%d",&ReadyNum);

     

    printf("输入每个就绪队列的CPU时间片: ");

    for(i = 0;i < ReadyNum; i++)

    {

    if((tmp = (ReadyQueue *)malloc(sizeof(ReadyQueue)))==NULL)

    {

    perror("malloc");

    exit(1);

    }

    scanf("%d",&(tmp->round)); /*输入此就绪队列中给每个进程所分配的CPU时间片*/

    tmp ->prio = 50 - tmp->round; /*设置其优先级,时间片越高,其优先级越低*/

    tmp ->LinkPCB = NULL; /*初始化其连接的进程队列为空*/

    tmp ->next = NULL;

    InsertPrio(tmp); /*按照优先级从高到低,建立多个就绪队列*/

    }

    }

    void GetFirst(ReadyQueue *queue) /*取得某一个就绪队列中的队头进程*/

    {

    run = queue ->LinkPCB;

    if(queue ->LinkPCB != NULL)

    {

    run ->state = 'R';

    queue ->LinkPCB = queue ->LinkPCB ->next;

    run ->next = NULL;

    }

    }

    void InsertLast(PCB *in,ReadyQueue *queue) /*将进程插入到就绪队列尾部*/

    {

    PCB *fst;

    fst = queue->LinkPCB;

    if( queue->LinkPCB == NULL)

    {

    in->next = queue->LinkPCB;

    queue->LinkPCB = in;

    }

    else

    {

    while(fst->next != NULL)

    {

    fst = fst->next;

    }

    in ->next = fst ->next;

    fst ->next = in;

    }

    }

    void ProcessCreate() /*进程创建函数*/

    {

    PCB *tmp;

    int i;

     

    printf("输入进程的个数: ");

    scanf("%d",&num);

    printf("输入进程名字和进程所需时间: ");

    for(i = 0;i < num; i++)

    {

    if((tmp = (PCB *)malloc(sizeof(PCB)))==NULL)

    {

    perror("malloc");

    exit(1);

    }

    scanf("%s",tmp->name);

    getchar(); /*吸收回车符号*/

    scanf("%d",&(tmp->needtime));

    tmp ->cputime = 0;

    tmp ->state ='W';

    tmp ->prio = 50 - tmp->needtime; /*设置其优先级,需要的时间越多,优先级越低*/

    tmp ->round = Head ->round;

    tmp ->count = 0;

    InsertLast(tmp,Head); /*按照优先级从高到低,插入到就绪队列*/

    }

    }

    void RoundRun(ReadyQueue *timechip) /*时间片轮转调度算法*/

    {

    int flag = 1;

    GetFirst(timechip);

    while(run != NULL)

    {

    while(flag)

    {

    run->count++;

    run->cputime++;

    run->needtime--;

    if(run->needtime == 0) /*进程执行完毕*/

    {

    run ->state = 'F';

    InsertFinish(run);

    flag = 0;

    }

    else if(run->count == timechip ->round)/*时间片用完*/

    {

    run->state = 'W';

    run->count = 0; /*计数器清零,为下次做准备*/

    InsertLast(run,timechip);

    flag = 0;

    }

    }

    flag = 1;

    GetFirst(timechip);

    }

    }

    void MultiDispatch() /*多级调度算法,每次执行一个时间片*/

    {

    int flag = 1;

    int k = 0;

    ReadyQueue *point;

    point = Head;

    GetFirst(point);

    while(run != NULL)

    {

    Output();

    if(Head ->LinkPCB!=NULL)

    point = Head;

    while(flag) {

    run->count++;

    run->cputime++;

    run->needtime--;

    if(run->needtime == 0) /*进程执行完毕*/

    {

    run ->state = 'F';

    InsertFinish(run);

    flag = 0;

    }

    else if(run->count == run->round)/*时间片用完*/

    {

    run->state = 'W';

    run->count = 0; /*计数器清零,为下次做准备*/

    if(point ->next!=NULL)

    {

    run ->round = point->next ->round;/*设置其时间片是下一个就绪队列的时间片*/

    InsertLast(run,point->next); /*将进程插入到下一个就绪队列中*/

    flag = 0;

    }

    else {

    RoundRun(point); /*如果为最后一个就绪队列就调用时间片轮转算法*/

    break;

    }

    }

    ++k;

    if(k == 3) {

    ProcessCreate();

    }

    }

    flag = 1;

    if(point ->LinkPCB == NULL)/*就绪队列指针下移*/

    point =point->next;

    if(point ->next ==NULL)

    {

    RoundRun(point);

    break;

    }

    GetFirst(point);

    }

    }

    五、算法流程图

    六、运行与测试

    用例描述:

     

    假设系统中有3个就绪队列Q1,Q2,Q3,时间片分别为2,4,8

    现在有3个作业J1,J2,J3它们所需要的CPU时间分别是3,2,1个时间片

     

    1、时刻0: J1到达。于是进入到队列1 , 运行1个时间片 , 时间片还未到,此时J2到达。

    2、时刻1: J2到达。 由于时间片仍然由J1掌控,于是等待。 J1在运行了1个时间片后,已经完成了在Q1中的2个时间片的限制,于是J1置于Q2等待被调度。现在处理机分配给J2。

    3、时刻2: J1进入Q2等待调度,J2获得CPU开始运行。

    4、时刻3:J3到达,由于J2的时间片未到,故J3在Q1等待调度,J1也在Q2等待调度。

    5、时刻4:J2处理完成,由于J3,J1都在等待调度,但是J3所在的队列比J1所在的队列的优先级要高,于是J3被调度,J1继续在Q2等待。

    6、时刻5:J3经过1个时间片,完成。

    7、时刻6:由于Q1已经空闲,于是开始调度Q2中的作业,则J1得到处理器开始运行。

    8、时刻7:J1再经过一个时间片,完成了任务。于是整个调度过程结束。

     

     

     

     

    运行截图:

    七、总结

     

    多级反馈队列调度算法体现了计算思维的调度特点,应用了先来先服务原则、应用时间片等做法使得每个申请者都能及时使用资源,是一种很好的协调整体的解决方案。

    不积跬步,无以至千里;不积小流,无以成江海。
  • 相关阅读:
    Codeforces Round 546 (Div. 2)
    Codeforces Round 545 (Div. 2)
    Codeforces Round 544(Div. 3)
    牛客小白月赛12
    Codeforces Round 261(Div. 2)
    Codeforces Round 260(Div. 2)
    Codeforces Round 259(Div. 2)
    Codeforces Round 258(Div. 2)
    Codeforces Round 257 (Div. 2)
    《A First Course in Probability》-chaper5-连续型随机变量-随机变量函数的分布
  • 原文地址:https://www.cnblogs.com/CCTVCHCH/p/14923957.html
Copyright © 2011-2022 走看看