zoukankan      html  css  js  c++  java
  • 1-短进程优先的调度算法详解[原创]

    一、SPF算法简介

    SJF算法

    • SJF(shortest job first)是以进程的运行时间长度作为优先级,进程运行时间越短,优先级越高。

    SJF算法的缺点

    • 必须预知进程的运行时间。即使是程序员也很难准确估计进程运行时间。如果估计过低,系统就可能按估计的时间终止进程的运行,但此时进程并未完成,故一般都会偏长估计
    • 对长进程不利。长进程的周转时间会明显地增长。可怕的是,SJF算法完全忽视进程等待时间,可能使进程等待时间过长,出现饥饿现象。
    • 人机无法实现交互。
    • 完全未考虑进程的紧迫程度。不能保证紧迫性进程得到及时处理。

      

                             

    二、算法流程图

     我做的流程图:http://www.processon.com/diagraming/5835692de4b086d1e79f81af

    三、源代码

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

     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 #include <string.h>
     4 
     5 /* run this program using the console pauser or add your own getch, system("pause") or input loop */
     6 
     7 
     8 struct pcb{
     9     char name[10];    //进程名 
    10     int arrival_time; //进程到达时间() 
    11     int start_time;   //进程开始时间 
    12     int need_time;      //进程运行所需时间 
    13     int finish_time;  //运行结束时间 
    14     struct pcb * link;   //链接下一个pcb的指针 
    15 };
    16 
    17 
    18 int num = 0;     //输入的进程数 
    19 typedef struct pcb PCB;    //定义结构体变量 
    20 /*
    21 结构体指针p指向 每新建的一个进程
    22 ready指针指向链表的第一个pcb 
    23 finish指针指向完成队列的第一个pcb结构体 
    24 */
    25 struct pcb *p = NULL, *ready = NULL, *finish = NULL;  

    2. 输入函数

     1 //用来测试链表建立,输入链表结构体数据 
     2 void print_test(){
     3     int i;
     4     struct pcb * test = ready;
     5     for(i=0;i<num;i++){
     6         printf("
    进程号:%d,进程名:%s,进程到达时间:%d,进程完成时间:%d",
     7                 i,test->name,test->arrival_time,test->need_time);
     8         if(NULL != test->link){
     9             test = test->link;
    10         }
    11         else{
    12             printf("
    test_link end
    ");
    13         }
    14         
    15     }
    16 }
    17 
    18 
    19 
    20 //输入函数,建立链表 
    21 void input(){
    22     int i;
    23     struct pcb * q;   //定义结构体变量 
    24     printf("请输入进程数:");
    25     scanf("%d", &num);
    26     for(i=0; i<num; i++){
    27         printf("
    进程号 NO.%d:", i);
    28         p = (struct pcb*)malloc(sizeof(struct pcb));
    29         printf("
    输入进程名:");
    30         scanf("%s", p->name);
    31         printf("
    请输入进程到达时间:");
    32         scanf("%d", &p->arrival_time);
    33         printf("
    请输入进程运行时间:");
    34         scanf("%d", &p->need_time);
    35         
    36         p->link = NULL;
    37         //建立链表
    38         if(NULL == ready){   //建立第一个结构体,使指针p,q指向它 
    39             ready = p;
    40             q = ready;
    41         } 
    42         else{      //链表建立 
    43             q->link = p;
    44             q = p;    
    45         }
    46         printf("input success");
    47     }
    48     print_test();   //测试链表是否建立 
    49 }

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

    1 //输出当前运行进程相关数据或者打印暂无进程运行 
    2 void output(struct pcb * p, int now_time){
    3     if(NULL == p){
    4         printf("当前时刻:%d, 暂无进程在运行!
    ", now_time);
    5     }
    6     else{
    7         printf("进程名:%s,到达时间:%d,运行需要时间:%d
    ",p->name,p->arrival_time,p->need_time);
    8     }
    9 }

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

     1 //sjf  shortest job first最短作业优先 
     2 struct pcb * SJF(int now_time, int * after){
     3     int min_time = 0;   //最短时间,即优先运行的进程的时间 
     4     struct pcb * now_progress = NULL, *p = ready;
     5     //遍历链表,查找出运行时间最短的进程 
     6     if (NULL != ready){
     7         while(NULL != p){
     8             if(now_time >= p->arrival_time){   //若进程已经到达,注意:时间单位为1 
     9                 /*
    10                 min_time = p->need_time;      //是错误的 
    11                 now_progress = p;
    12                 if(p->need_time < min_time){
    13                     min_time = p->need_time;
    14                     now_progress = p;
    15                 } */
    16                 if(0 == min_time){  //给最短时间赋初值
    17                     now_progress = p;
    18                     min_time = p->need_time;                    
    19                 }
    20                 else{
    21                     if(p->need_time < min_time){
    22                         now_progress = p;
    23                         min_time = p->need_time;
    24                     }
    25                 }
    26             }
    27             p = p->link;
    28         }
    29     }
    30     *after = min_time + now_time;
    31     printf("
    SJF:a shortest progress running!
    ");
    32     return now_progress;   //返回指向正在运行进程的指针 
    33 }

    4. 进程执行完毕

     1 //将已经运行完成的进程添加到finish队列,并且进程数减一 
     2 void destory(struct pcb * p, int now_time){
     3     printf("destory start!
    "); 
     4     struct pcb * q = ready;
     5     struct pcb * f = NULL;   //用于finish链表的添加 
     6 
     7     
     8     if(strcmp(p->name, ready->name) == 0){  //若第一个进程完成 
     9         ready = ready->link;
    10     }
    11     //若中间或最后一个进程完成 
    12     else{
    13         q = ready;
    14         while((strcmp(q->link->name,p->name) != 0) && NULL != q->link){
    15             q = q->link;
    16         }
    17         q->link = p->link;
    18     }
    19     
    20      p->finish_time = now_time;    //结束时间
    21      p->start_time =  now_time - p->need_time;  //开始时间 
    22      
    23     //将已经运行的进程添加到finish队列
    24     if(NULL == finish){
    25         finish = p;    //finish指向完成链表的表头 
    26         p->link = NULL;
    27     }
    28     else{
    29         f = finish;
    30         while(NULL != f->link){
    31             f = f->link;
    32         }
    33         f->link = p;
    34         p->link = NULL;
    35     }
    36     
    37     num--;   //进程数减一 
    38     printf("
    destory success!
    ");
    39 }

    5. 主函数

     1 int main(int argc, char *argv[]) {
     2     
     3     
     4     input();  //调用输入函数 
     5     
     6     int now_time = 0;    //初始时间为0 
     7     int after = 0;        //执行完一个进程后的时间:优先运行进程的运行时间+当前时间 
     8     struct pcb * now_progress = NULL;    //now_progress指向正在运行的进程(结构体) 
     9     struct pcb *m = NULL;
    10     
    11     while(num > 0){    //进程数大于0,每次循环num会减一 
    12         printf("start SJF");
    13         now_progress = SJF(now_time, &after);  //调用SJF函数,遍历链表 
    14 
    15         
    16         if(NULL != now_progress){
    17             /*进程执行,每循环一次,当前时间加一
    18               同时要判断当前时间是否有进程刚好到达正在在等待 */
    19             for(;now_time < after; now_time++){
    20                 printf("
    当前时刻:%d", now_time);
    21                 printf("
    -----------当前执行进程------------
    ");
    22                 output(now_progress, now_time);     //调用output函数 
    23                 printf("
    -----------等待执行进程------------
    ");
    24                 
    25                 m = ready;
    26                 while(NULL != m){   //循环,若当前时间有进程到达,打印相关信息 
    27                     if(m != now_progress){
    28                         if(m->arrival_time <= now_time){
    29                             output(m, now_time);
    30                             printf("
    a new progress arrival
    ");
    31                         }
    32                     }
    33                     m = m->link;
    34                 }
    35             }
    36             //进程执行完后调用destory函数 
    37             destory(now_progress, now_time);
    38 
    39         }
    40         else{   //没有进程在运行 
    41             output(now_progress, now_time);
    42             now_time++;
    43         }
    44         
    45     }
    46     output_all();
    47     return 0;
    48     
    49 }

     我写得这么清楚,加上我画的流程图,相信你可以懂的~~

    四、测试

     

    五、坑

    原本这个函数我是这样写的,但发现运行结果不对~

     按上面代码的运行结果:

     

    按理说,a进程执行后不应该是e进程执行,应该是运行时间最短的d进程执行。同理之后是b, e, c;

    我又回去看前面的代码,改正如下:

    运行结果:

    六、总结知识点

    1. p = (struct pcb*)malloc(sizeof(struct pcb))与p = (struct pcb*)malloc(sizeof(PCB))相同, PCB是结构体struct pcb的一个结构体变量。

    2. 在使用字符串处理函数(puts,gets,strcat,strcpy,strcmp,strlen,strlwr)时,应当在程序文件的开头用#include<string.h>,把"string.h"文件包含到本文件中。
    3. malloc函数。比如:malloc(100) 开辟100字节的临时分配域,函数值为其第1个字节的地址。只提供一个地址。若函数不能成功执行(比如内存不足),则返回空指针。(int*)malloc(sizeof(int)) 将申请得到的空间地址转换成了int类型空间地址最后就可以赋值给指向int型空间的p指针了。

    总代码

      1 #include <stdio.h>
      2 #include <stdlib.h>
      3 #include <string.h>
      4 
      5 /* run this program using the console pauser or add your own getch, system("pause") or input loop */
      6 
      7 
      8 struct pcb{
      9     char name[10];    //进程名 
     10     int arrival_time; //进程到达时间() 
     11     int start_time;   //进程开始时间 
     12     int need_time;      //进程运行所需时间 
     13     int finish_time;  //运行结束时间 
     14     struct pcb * link;   //链接下一个pcb的指针 
     15 };
     16 
     17 
     18 int num = 0;     //输入的进程数 
     19 typedef struct pcb PCB;    //定义结构体变量 
     20 /*
     21 结构体指针p指向 每新建的一个进程
     22 ready指针指向链表的第一个pcb 
     23 finish指针指向完成队列的第一个pcb结构体 
     24 */
     25 struct pcb *p = NULL, *ready = NULL, *finish = NULL;  
     26 
     27 
     28 //用来测试链表建立,输入链表结构体数据 
     29 void print_test(){
     30     int i;
     31     struct pcb * test = ready;
     32     for(i=0;i<num;i++){
     33         printf("
    进程号:%d,进程名:%s,进程到达时间:%d,进程完成时间:%d",
     34                 i,test->name,test->arrival_time,test->need_time);
     35         if(NULL != test->link){
     36             test = test->link;
     37         }
     38         else{
     39             printf("
    test_link end
    ");
     40         }
     41         
     42     }
     43 }
     44 
     45 
     46 
     47 //输入函数,建立链表 
     48 void input(){
     49     int i;
     50     struct pcb * q;   //定义结构体变量 
     51     printf("请输入进程数:");
     52     scanf("%d", &num);
     53     for(i=0; i<num; i++){
     54         printf("
    进程号 NO.%d:", i);
     55         p = (struct pcb*)malloc(sizeof(struct pcb));
     56         printf("
    输入进程名:");
     57         scanf("%s", p->name);
     58         printf("
    请输入进程到达时间:");
     59         scanf("%d", &p->arrival_time);
     60         printf("
    请输入进程运行时间:");
     61         scanf("%d", &p->need_time);
     62         
     63         p->link = NULL;
     64         //建立链表
     65         if(NULL == ready){   //建立第一个结构体,使指针p,q指向它 
     66             ready = p;
     67             q = ready;
     68         } 
     69         else{      //链表建立 
     70             q->link = p;
     71             q = p;    
     72         }
     73         printf("input success");
     74     }
     75     print_test();   //测试链表是否建立 
     76 }
     77 
     78 
     79 
     80 //sjf  shortest job first最短作业优先 
     81 struct pcb * SJF(int now_time, int * after){
     82     int min_time = 0;   //最短时间,即优先运行的进程的时间 
     83     struct pcb * now_progress = NULL, *p = ready;
     84     //遍历链表,查找出运行时间最短的进程 
     85     if (NULL != ready){
     86         while(NULL != p){
     87             if(now_time >= p->arrival_time){   //若进程已经到达,注意:时间单位为1 
     88                 /*
     89                 min_time = p->need_time;      //是错误的 
     90                 now_progress = p;
     91                 if(p->need_time < min_time){
     92                     min_time = p->need_time;
     93                     now_progress = p;
     94                 } */
     95                 if(0 == min_time){  //给最短时间赋初值
     96                     now_progress = p;
     97                     min_time = p->need_time;                    
     98                 }
     99                 else{
    100                     if(p->need_time < min_time){
    101                         now_progress = p;
    102                         min_time = p->need_time;
    103                     }
    104                 }
    105             }
    106             p = p->link;
    107         }
    108     }
    109     *after = min_time + now_time;
    110     printf("
    SJF:a shortest progress running!
    ");
    111     return now_progress;   //返回指向正在运行进程的指针 
    112 }
    113 
    114 
    115 //输出当前运行进程相关数据或者打印暂无进程运行 
    116 void output(struct pcb * p, int now_time){
    117     if(NULL == p){
    118         printf("当前时刻:%d, 暂无进程在运行!
    ", now_time);
    119     }
    120     else{
    121         printf("进程名:%s,到达时间:%d,运行需要时间:%d
    ",p->name,p->arrival_time,p->need_time);
    122     }
    123 }
    124 
    125 
    126 //将已经运行完成的进程添加到finish队列,并且进程数减一 
    127 void destory(struct pcb * p, int now_time){
    128     printf("destory start!
    "); 
    129     struct pcb * q = ready;
    130     struct pcb * f = NULL;   //用于finish链表的添加 
    131 
    132     
    133     if(strcmp(p->name, ready->name) == 0){  //若第一个进程完成 
    134         ready = ready->link;
    135     }
    136     //若中间或最后一个进程完成 
    137     else{
    138         q = ready;
    139         while((strcmp(q->link->name,p->name) != 0) && NULL != q->link){
    140             q = q->link;
    141         }
    142         q->link = p->link;
    143     }
    144     
    145      p->finish_time = now_time;    //结束时间
    146      p->start_time =  now_time - p->need_time;  //开始时间 
    147      
    148     //将已经运行的进程添加到finish队列
    149     if(NULL == finish){
    150         finish = p;    //finish指向完成链表的表头 
    151         p->link = NULL;
    152     }
    153     else{
    154         f = finish;
    155         while(NULL != f->link){
    156             f = f->link;
    157         }
    158         f->link = p;
    159         p->link = NULL;
    160     }
    161     
    162     num--;   //进程数减一 
    163     printf("
    destory success!
    ");
    164 }
    165 
    166 
    167 
    168 void output_all(){
    169     struct pcb * p = finish;
    170     printf("
    ---------------统计结果----------------
    ");
    171     while(NULL != p){
    172         printf("
    进程名:%s,开始时间:%d,结束时间:%d,运行时间:%d,到达时间:%d",
    173                 p->name,p->start_time,p->finish_time,p->need_time,p->arrival_time);
    174         p = p->link;
    175     }
    176 }
    177 
    178 
    179 
    180 int main(int argc, char *argv[]) {
    181     
    182     
    183     input();  //调用输入函数 
    184     
    185     int now_time = 0;    //初始时间为0 
    186     int after = 0;        //执行完一个进程后的时间:优先运行进程的运行时间+当前时间 
    187     struct pcb * now_progress = NULL;    //now_progress指向正在运行的进程(结构体) 
    188     struct pcb *m = NULL;
    189     
    190     while(num > 0){    //进程数大于0,每次循环num会减一 
    191         printf("start SJF");
    192         now_progress = SJF(now_time, &after);  //调用SJF函数,遍历链表 
    193 
    194         
    195         if(NULL != now_progress){
    196             /*进程执行,每循环一次,当前时间加一
    197               同时要判断当前时间是否有进程刚好到达正在在等待 */
    198             for(;now_time < after; now_time++){
    199                 printf("
    当前时刻:%d", now_time);
    200                 printf("
    -----------当前执行进程------------
    ");
    201                 output(now_progress, now_time);     //调用output函数 
    202                 printf("
    -----------等待执行进程------------
    ");
    203                 
    204                 m = ready;
    205                 while(NULL != m){   //循环,若当前时间有进程到达,打印相关信息 
    206                     if(m != now_progress){
    207                         if(m->arrival_time <= now_time){
    208                             output(m, now_time);
    209                             printf("
    a new progress arrival
    ");
    210                         }
    211                     }
    212                     m = m->link;
    213                 }
    214             }
    215             //进程执行完后调用destory函数 
    216             destory(now_progress, now_time);
    217 
    218         }
    219         else{   //没有进程在运行 
    220             output(now_progress, now_time);
    221             now_time++;
    222         }
    223         
    224     }
    225     output_all();
    226     return 0;
    227     
    228 }
    View Code
  • 相关阅读:
    【从0安装】安装pycharm
    【从0安装】安装appium
    【从0安装】安装android sdk
    【从0安装】安装java jdk
    【从0安装】安装nodejs
    【技术解析】如何用Docker实现SequoiaDB集群的快速部署
    巨杉数据库助力民生银行、广发银行前台智慧化业务
    巨杉数据库入选Gartner数据库报告,中国首家入选厂商
    【操作教程】利用YCSB测试巨杉数据库性能
    巨杉数据库首批入选广州数字金融协会,引领大湾区数字金融创新
  • 原文地址:https://www.cnblogs.com/0zcl/p/6094942.html
Copyright © 2011-2022 走看看