• 进程调度模拟算法


    一、目的和要求

    进程调度是处理机管理的核心内容。本实验要求用高级语言编写模拟进程调度程序,以便加深理解有关进程控制快、进程队列等概念,并体会和了解优先数算法和时间片轮转算法的具体实施办法。

    二、实验内容

    1.设计进程控制块PCB的结构,通常应包括如下信息:

        进程名、进程优先数(或轮转时间片数)、进程已占用的CPU时间、进程到完成还需要的时间、进程的状态、当前队列指针等。

      2.编写两种调度算法程序:

        优先数调度算法程序

        循环轮转调度算法程序

    3.按要求输出结果。      

    三、提示和说明

        分别用两种调度算法对伍个进程进行调度。每个进程可有三种状态;执行状态(RUN)、就绪状态(READY,包括等待状态)和完成状态(FINISH),并假定初始状态为就绪状态。

      (一)进程控制块结构如下:

          NAME——进程标示符

          PRIO/ROUND——进程优先数/进程每次轮转的时间片数(设为常数2)

          CPUTIME——进程累计占用CPU的时间片数

          NEEDTIME——进程到完成还需要的时间片数

          STATE——进程状态

          NEXT——链指针

        注:

        1.为了便于处理,程序中进程的的运行时间以时间片为单位进行计算;

        2.各进程的优先数或轮转时间片数,以及进程运行时间片数的初值,均由用户在程序运行时给定。

      (二)进程的就绪态和等待态均为链表结构,共有四个指针如下:

          RUN——当前运行进程指针

          READY——就需队列头指针

          TAIL—— 就需队列尾指针

          FINISH—— 完成队列头指针

    (三)程序说明

        1. 在优先数算法中,进程优先数的初值设为:

          50-NEEDTIME

    每执行一次,优先数减1,CPU时间片数加1,进程还需要的时间片数减1。

        在轮转法中,采用固定时间片单位(两个时间片为一个单位),进程每轮转一次,CPU时间片数加2,进程还需要的时间片数减2,并退出CPU,排到就绪队列尾,等待下一次调度。

        2. 程序的模块结构提示如下:

        整个程序可由主程序和如下7个过程组成:

        (1)INSERT1——在优先数算法中,将尚未完成的PCB按优先数顺序插入到就绪队列中;

        (2)INSERT2——在轮转法中,将执行了一个时间片单位(为2),但尚未完成的进程的PCB,插到就绪队列的队尾;

        (3)FIRSTIN——调度就绪队列的第一个进程投入运行;

        (4)PRINT——显示每执行一次后所有进程的状态及有关信息。

        (5)CREATE——创建新进程,并将它的PCB插入就绪队列;

        (6)PRISCH——按优先数算法调度进程;

        (7)ROUNDSCH——按时间片轮转法调度进程。

        主程序定义PCB结构和其他有关变量。

    (四)运行和显示

        程序开始运行后,首先提示:请用户选择算法,输入进程名和相应的NEEDTIME值。

        每次显示结果均为如下5个字段:

          name   cputime   needtime   priority   state

        注:

        1.在state字段中,"R"代表执行态,"W"代表就绪(等待)态,"F"代表完成态。

    2.应先显示"R"态的,再显示"W"态的,再显示"F"态的。

      3.在"W"态中,以优先数高低或轮转顺序排队;在"F"态中,以完成先后顺序排队。

    实验报告

    一、实验目的

    进程调度是处理机管理的核心内容。本实验要求用高级语言编写模拟进程调度程序,以便加深理解有关进程控制快、进程队列等概念,并体会和了解优先数算法和时间片轮转算法的具体实施办法。

    二、实验内容和要求

    1. 设计进程控制块PCB的结构,通常应包括:进程名、进程优先数(或轮转时间片数)、进程已占用的CPU时间、进程到完成还需要的时间、进程的状态、当前队列指针等。
    2. 编写两种调度算法程序:

    1)  优先数调度算法程序;

    2)  循环轮转调度算法程序。

    1. 程序源代码和运行截图写入实验报告并提交

    、实验步骤

    1. 实验准备

    (1) 查阅相关资料;

    编写两种调度算法的程序参考了比较多的内容,首先参考了教材,将两种调度算法又重新复习了一下,增加了一下理论的掌握情况,然后又根据实验报告上的要求进行了主体的搭建,具体细节的实现主要参考了一些网上的文章。主要包括下面三篇文章。

    https://www.doc88.com/p-1146521830717.html?s=rel&id=1

    https://www.doc88.com/p-9197402934769.html?s=rel&id=4

     

    https://blog.csdn.net/c1194758555/article/details/53047570?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522165142364816782248521163%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=165142364816782248521163&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_ecpm_v1~rank_v31_ecpm-13-53047570.142^v9^pc_search_result_cache,157^v4^control&utm_term=%E6%97%B6%E9%97%B4%E7%89%87%E8%BD%AE%E8%BD%AC%E7%AE%97%E6%B3%95%E5%92%8C%E4%BC%98%E5%85%88%E7%BA%A7%E8%B0%83%E5%BA%A6%E7%AE%97%E6%B3%95&spm=1018.2226.3001.4187

     

    (2) 初步编写程序;

    进程调度算法程序主体框架:

    int main(void) {
    char chose;
    printf("请输入要创建的进程数目:\n");
    scanf("%d", &num);
    getchar();
    printf("输入进程的调度方法:P/R)\n");
    scanf("%c", &chose);
    switch (chose) {
    case 'P':
    case 'p':
    
    PrioCreate();
    
    Priority();
    
    break;
    
    case 'R':
    
    case 'r':
    
    TimeCreate();
    
    RoundRun();
    
    break;
    
    default:break;
    
    }
    
    OutPut();
    
    return 0;
    
    }

     

     

     

    (3) 准备测试数据;

    进程调度模拟算法,数据输入格式

    a 10b 13

    c 3

    d 15

    e 8

    1. 上机调试

     

    1. 主要流程和源代码

    主要流程

    首先输入进程数目,然后选择调度算法的类型,然后在输入哥进程的名称和执行时间,具体如下图所示:

     

    源代码:

    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #include<windows.h>
    #pragma warning(disable:4996)
    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;
    
    PCB* ready = NULL, * run = NULL, * finish = NULL;    //定义三个队列,就绪队列,执行队列,完成队列
    int num;
    void GetFirst();        //从就绪队列取得第一个节点
    
    void OutPut();    //输出队列信息
    
    void InsertPrio(PCB* in);//创建优先级队列,规定优先数越小,优先级越高
    
    void InsertTime(PCB* in);    //时间片队列
    
    void InsertFinish(PCB* in);    //时间片队列
    
    void PrioCreate();        //优先级输入函数
    
    void TimeCreate();        //时间片输入函数
    
    void Priority();        //按照优先级调度
    
    void RoundRun();        //时间片轮转调度
    
    int main(void) {
        char chose;
        printf("请输入要创建的进程数目:\n");
        scanf("%d", &num);
        getchar();
        printf("输入进程的调度方法:P/R)\n");
        scanf("%c", &chose);
        switch (chose) {
        case 'P':
        case 'p':
            PrioCreate();
            Priority();
            break;
        case 'R':
        case 'r':
            TimeCreate();
            RoundRun();
            break;
        default:break;
        }
        OutPut();
        return 0;
    }
    
    
    //取得第一个就绪队列节点
    void GetFirst() {
        run = ready;
        if (ready != NULL) {
            run->state = 'R';
            ready = ready->next;
            run->next = NULL;
        }
    }
    
    //输出队列信息
    void OutPut() {
        PCB* p;
        printf("进程名\t优先级\t轮数\tcpu时间\t需要时间\t进程状态\t计数器\n");
        p = run;
        while (p != NULL) {
            printf("%s\t%d\t%d\t%d\t%d\t\t%c\t\t%d\n", p->name, p->prio, p->round, p->cputime, p->needtime, p->state, p->count);
            p = p->next;
        }
        p = ready;
    
        while (p != NULL) {
            printf("%s\t%d\t%d\t%d\t%d\t\t%c\t\t%d\n", p->name, p->prio, p->round, p->cputime, p->needtime, p->state, p->count);
            p = p->next;
        }
        p = finish;
        while (p != NULL)
        {
            printf("%s\t%d\t%d\t%d\t%d\t\t%c\t\t%d\n", p->name, p->prio, p->round, p->cputime, p->needtime, p->state, p->count);
            p = p->next;
        }
    
    }
    
    void InsertPrio(PCB* in) {
        //
        PCB* fst, * nxt;
        fst = nxt = ready;
    
        if (ready == NULL) {
            //如果队列为空,则为第一个元素
            in->next = ready;
            ready = in;
        }
        else {
            //查到合适的位置进行插入
            if (in->prio >= fst->prio)
            {
                //比第一个还要大,则插入到队头,
                in->next = ready;
                ready = in;
            }
            else
            {
                while (fst->next != NULL) {
                    //移动指针查找到第一个比它小的元素的位置进行插入
                    nxt = fst->next;
                    if (fst->next->prio < in->prio) {
                        break;
                    }
                    fst = fst->next;
                }
                if (fst->next == NULL) {
                    //已经搜索到队尾,则优先级数最下角,将其插入到队尾即可
                    in->next = fst->next;
                    fst->next = in;
                }
                else {
                    //插入到队列中
                    fst->next = in;
                    in->next = nxt;
                }
            }
        }
    }
    
    
    void InsertTime(PCB* in) {
        //将进程插入到就绪队列尾部
        PCB* fst;
        fst = ready;
        if (ready == NULL) {
            in->next = ready;
            ready = in;
        }
        else {
            while (fst->next != NULL)
            {
                //            if(fst->prio<in->prio)
                //                break;
                //            if(fst->prio<in->prio){
                //                temp=fst->next;
                //                fst->next=in;
                //                in->next=temp;
                //                break;
                //            }
                fst = fst->next;
    
            }
            in->next = fst->next;
            fst->next = in;
        }
    }
    
    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 PrioCreate() {
        //优先级调度输入函数
        PCB* tmp;
        int i;
        printf("输入进程名字和进程所需要的时间:\n");
        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 = 0;
            tmp->count = 0;
            InsertPrio(tmp);//按照优先级从高到低,插入到就绪队列 
        }
    }
    
    void TimeCreate() {
        //时间片输入函数
        PCB* tmp;
        int i;
        printf("输入进程名字和进程时间片所需要的时间\n");
        for (int 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 = 0;
            tmp->round = 2;
            tmp->count = 0;
            InsertTime(tmp);
        }
    }
    
    //按照优先级调度,每次执行一个时间片
    void Priority() {
        int flag = 1;
        GetFirst();
        while (run != NULL) {
            //当就绪队列不为空时,则调度进程如执行队列执行
            OutPut();//输出每次调度过程中各个节点的状态
            while (flag) {
                run->prio -= 1;//优先级减去1
                run->cputime++;//cpu时间片加一
                run->needtime--;//进程执行完成的剩余时间减一
                if (run->needtime == 0) {
                    //如果进程执行完毕,将进程状态置为F,将其插入到完成队列
                    run->state = 'F';
                    run->count++;//进程执行的次数加1
                    InsertFinish(run);
                    flag = 0;
                }
                else {
                    //将进程的状态置为W,入就绪队列
                    run->state = 'W';
                    run->count++;//进程执行的次数加1
                    InsertPrio(run);
                    flag = 0;
                }
                Sleep(500);
            }
            flag = 1;
            GetFirst();//继续取就绪队列队头进程进入执行队列 
        }
    }
    
    void RoundRun() {
        //时间片轮转调度算法
        int flag = 1;
        GetFirst();
        while (run != NULL) {
            OutPut();
            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;
                    InsertTime(run);
                    flag = 0;
                }
                Sleep(500);
            }
            flag = 1;
            GetFirst();
    
        }
    }
  • 相关阅读:
    东南大学2021年数学分析考研试卷
    东南大学2021年高等代数考研试卷
    东南大学2021年高等代数考研试卷
    东华大学2021年数学分析考研试卷
    东华大学2021年高等代数考研试卷
    [Oracle 工程师手记]探究 Oracle PDB Application Container (二)
    [Oracle 工程师手记]探究 Oracle PDB Application Container (一)
    Jenkins Extended choice parameter和Active Choices param 之Groovy Script使用
    C#异步调用,成功回调中更新界面(线程间操作无效)
    C#使用非托管 DLL 函数
  • 原文地址:https://www.cnblogs.com/wfswf/p/16367048.html
Copyright © 2020-2023  润新知