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("\n進程號:%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("\ntest_link end\n");
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("\n進程號 NO.%d:", i);
28         p = (struct pcb*)malloc(sizeof(struct pcb));
29         printf("\n輸入進程名:");
30         scanf("%s", p->name);
31         printf("\n請輸入進程到達時間:");
32         scanf("%d", &p->arrival_time);
33         printf("\n請輸入進程運行時間:");
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, 暫無進程在運行!\n", now_time);
5     }
6     else{
7         printf("進程名:%s,到達時間:%d,運行需要時間:%d\n",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("\nSJF:a shortest progress running!\n");
32     return now_progress;   //返回指向正在運行進程的指針 
33 }

 

 

4. 進程執行完畢

 1 //將已經運行完成的進程添加到finish隊列,並且進程數減一 
 2 void destory(struct pcb * p, int now_time){
 3     printf("destory start!\n"); 
 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("\ndestory success!\n");
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("\n當前時刻:%d", now_time);
21                 printf("\n-----------當前執行進程------------\n");
22                 output(now_progress, now_time);     //調用output函數 
23                 printf("\n-----------等待執行進程------------\n");
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("\na new progress arrival\n");
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("\n進程號:%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("\ntest_link end\n");
 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("\n進程號 NO.%d:", i);
 55         p = (struct pcb*)malloc(sizeof(struct pcb));
 56         printf("\n輸入進程名:");
 57         scanf("%s", p->name);
 58         printf("\n請輸入進程到達時間:");
 59         scanf("%d", &p->arrival_time);
 60         printf("\n請輸入進程運行時間:");
 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("\nSJF:a shortest progress running!\n");
111     return now_progress;   //返回指向正在運行進程的指針 
112 }
113 
114 
115 //輸出當前運行進程相關數據或者打印暫無進程運行 
116 void output(struct pcb * p, int now_time){
117     if(NULL == p){
118         printf("當前時刻:%d, 暫無進程在運行!\n", now_time);
119     }
120     else{
121         printf("進程名:%s,到達時間:%d,運行需要時間:%d\n",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!\n"); 
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("\ndestory success!\n");
164 }
165 
166 
167 
168 void output_all(){
169     struct pcb * p = finish;
170     printf("\n---------------統計結果----------------\n");
171     while(NULL != p){
172         printf("\n進程名:%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("\n當前時刻:%d", now_time);
200                 printf("\n-----------當前執行進程------------\n");
201                 output(now_progress, now_time);     //調用output函數 
202                 printf("\n-----------等待執行進程------------\n");
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("\na new progress arrival\n");
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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM