“短进程优先”调度算法

实验一  进程调度

一、实验目的

    编写并调试一个模拟的进程调度程序,以加深对进程的概念及进程调度算法的理解.

二、实验内容

  1. 调试运行“短进程优先”调度算法,给出运行结果。
  2. 采用“短进程优先”调度算法对五个进程进行调度。每个进程有一个进程控制块( PCB)表示。进程控制块可以包含如下信息:进程名、到达时间、需要运行时间、已用CPU时间、进程状态等等。
  3. 每个进程的状态可以是就绪 W(Wait)、运行R(Run)、或完成F(Finish)三种状态之一。 每进行一次调度程序都打印一次运行进程、就绪队列、以及各个进程的 PCB,以便进行检查。重复以上过程,直到所要进程都完成为止。

 

三、实现思路

 

1.  变量声明与结构体定义

2.  输入函数

3.  所有进程结束后,输出所有进程信息

4.  找出运行时间最短的进程

5. 进程执行完毕

6. 主函数

 

四、主要的数据结构

1. 变量声明与结构体定义

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

 

/* run this program using the console pauser or add your own getch, system("pause") or input loop */

 

struct pcb{

    char name[10];    //进程名

    int arrival_time; //进程到达时间()

    int start_time;   //进程开始时间

    int need_time;      //进程运行所需时间

    int finish_time;  //运行结束时间

    struct pcb * link;   //链接下一个pcb的指针

};

int num = 0;     //输入的进程数

typedef struct pcb PCB;    //定义结构体变量

/*

结构体指针p指向 每新建的一个进程

ready指针指向链表的第一个pcb

finish指针指向完成队列的第一个pcb结构体

*/

struct pcb *p = NULL, *ready = NULL, *finish = NULL;

 

 

2. 输入函数

//用来测试链表建立,输入链表结构体数据

void print_test(){

    int i;

    struct pcb * test = ready;

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

        printf("\n进程号:%d,进程名:%s,进程到达时间:%d,进程完成时间:%d",

                i,test->name,test->arrival_time,test->need_time);

        if(NULL != test->link){

            test = test->link;

        }

        else{

            printf("\ntest_link end\n");

        }

       

    }

}

 

 

 

//输入函数,建立链表

void input(){

    int i;

    struct pcb * q;   //定义结构体变量

    printf("请输入进程数:");

    scanf("%d", &num);

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

        printf("\n进程号 NO.%d:", i);

        p = (struct pcb*)malloc(sizeof(struct pcb));

        printf("\n输入进程名:");

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

        printf("\n请输入进程到达时间:");

        scanf("%d", &p->arrival_time);

        printf("\n请输入进程运行时间:");

        scanf("%d", &p->need_time);

        

        p->link = NULL;

        //建立链表

        if(NULL == ready){   //建立第一个结构体,使指针p,q指向它

            ready = p;

            q = ready;

        }

        else{      //链表建立

            q->link = p;

            q = p;   

        }

        printf("input success");

    }

    print_test();   //测试链表是否建立

}

3.所有进程结束后,输出所有进程信息

//输出当前运行进程相关数据或者打印暂无进程运行

void output(struct pcb * p, int now_time){

    if(NULL == p){

        printf("当前时刻:%d, 暂无进程在运行!\n", now_time);

    }

    else{

        printf("进程名:%s,到达时间:%d,运行需要时间:%d\n",p->name,p->arrival_time,p->need_time);

    }

}

 

  1. 4.  找出运行时间最短的进程

//sjf  shortest job first最短作业优先

struct pcb * SJF(int now_time, int * after){

    int min_time = 0;   //最短时间,即优先运行的进程的时间

    struct pcb * now_progress = NULL, *p = ready;

    //遍历链表,查找出运行时间最短的进程

    if (NULL != ready){

        while(NULL != p){

            if(now_time >= p->arrival_time){   //若进程已经到达,注意:时间单位为1

                /*

                min_time = p->need_time;      //是错误的

                now_progress = p;

                if(p->need_time < min_time){

                    min_time = p->need_time;

                    now_progress = p;

                } */

                if(0 == min_time){  //给最短时间赋初值

                    now_progress = p;

                    min_time = p->need_time;                   

                }

                else{

                    if(p->need_time < min_time){

                        now_progress = p;

                        min_time = p->need_time;

                    }

                }

            }

            p = p->link;

        }

    }

    *after = min_time + now_time;

    printf("\nSJF:a shortest progress running!\n");

    return now_progress;   //返回指向正在运行进程的指针

}

 

5. 进程执行完毕

//将已经运行完成的进程添加到finish队列,并且进程数减一

void destory(struct pcb * p, int now_time){

    printf("destory start!\n");

    struct pcb * q = ready;

    struct pcb * f = NULL;   //用于finish链表的添加

 

   

    if(strcmp(p->name, ready->name) == 0){  //若第一个进程完成

        ready = ready->link;

    }

    //若中间或最后一个进程完成

    else{

        q = ready;

        while((strcmp(q->link->name,p->name) != 0) && NULL != q->link){

            q = q->link;

        }

        q->link = p->link;

    }

   

     p->finish_time = now_time;    //结束时间

     p->start_time =  now_time - p->need_time;  //开始时间

    

    //将已经运行的进程添加到finish队列

    if(NULL == finish){

        finish = p;    //finish指向完成链表的表头

        p->link = NULL;

    }

    else{

        f = finish;

        while(NULL != f->link){

            f = f->link;

        }

        f->link = p;

        p->link = NULL;

    }

   

    num--;   //进程数减一

    printf("\ndestory success!\n");

}

主函数

int main(int argc, char *argv[]) {

   

   

    input();  //调用输入函数

   

    int now_time = 0;    //初始时间为0

    int after = 0;        //执行完一个进程后的时间:优先运行进程的运行时间+当前时间

    struct pcb * now_progress = NULL;    //now_progress指向正在运行的进程(结构体)

    struct pcb *m = NULL;

   

    while(num > 0){    //进程数大于0,每次循环num会减一

        printf("start SJF");

        now_progress = SJF(now_time, &after);  //调用SJF函数,遍历链表

 

       

        if(NULL != now_progress){

            /*进程执行,每循环一次,当前时间加一

              同时要判断当前时间是否有进程刚好到达正在在等待 */

            for(;now_time < after; now_time++){

                printf("\n当前时刻:%d", now_time);

                printf("\n-----------当前执行进程------------\n");

                output(now_progress, now_time);     //调用output函数

                printf("\n-----------等待执行进程------------\n");

               

                m = ready;

                while(NULL != m){   //循环,若当前时间有进程到达,打印相关信息

                    if(m != now_progress){

                        if(m->arrival_time <= now_time){

                            output(m, now_time);

                            printf("\na new progress arrival\n");

                        }

                    }

                    m = m->link;

                }

            }

            //进程执行完后调用destory函数

            destory(now_progress, now_time);

 

        }

        else{   //没有进程在运行

            output(now_progress, now_time);

            now_time++;

        }

       

    }

    output_all();

    return 0;

   

}

五、算法流程图

 

 

 

六、运行与测试(系统运行截图)

 

 

 

 

 

 

 

 

 

 

 

 

 

 

七、总结

 

SJF算法是以进程的运行时间长度作为优先级,进程运行时间越短,优先级越高。

缺点

必须预知进程的运行时间。即使是程序员也很难准确估计进程运行时间。如果估计过低,系统就可能按估计的时间终止进程的运行,但此时进程并未完成,故一般都会偏长估计

对长进程不利。长进程的周转时间会明显地增长。可怕的是,SJF算法完全忽视进程等待时间,可能使进程等待时间过长,出现饥饿现象。

人机无法实现交互。

完全未考虑进程的紧迫程度。不能保证紧迫性进程得到及时处理。

 

 

问题:对比说明短进程优先和动态优先数中PCB的定义有什么不同?

posted @ 2021-06-23 16:59  小白冲  阅读(1579)  评论(0编辑  收藏  举报