系统相关
首页 > 系统相关> > 进程调度模拟算法

进程调度模拟算法

作者:互联网

 

一、目的和要求

 

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

 

二、实验内容

 

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. 上机调试
  2.  

     

 

  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();

    }
}

 

标签:run,队列,调度,next,PCB,算法,fst,进程,模拟
来源: https://www.cnblogs.com/wfswf/p/16367048.html