1. 程式人生 > >作業系統程序排程演算法實現2

作業系統程序排程演算法實現2

實驗三 程序排程

一、實驗目的

1、 理解有關程序控制塊、程序佇列的概念。
2、 掌握程序優先權排程演算法和時間片輪轉排程演算法的處理邏輯。
二、實驗內容與基本要求

1、 設計程序控制塊PCB的結構,分別適用於優先權排程演算法和時間片輪轉排程演算法。
2、 建立程序就緒佇列。
3、 編制兩種程序排程演算法:優先權排程演算法和時間片輪轉排程演算法。
三、實驗報告要求

1、 優先權排程演算法和時間片輪轉排程演算法原理。
2、 程式流程圖。
3、 程式及註釋。
4、 執行結果以及結論。
四、實驗報告

1.時間片輪轉排程演算法(round robin)

a.該演算法採取了非常公平的方式,即讓就緒佇列上的每個程序每次僅執行一個時間片。如果就緒佇列上有N個程序,則每個程序每次大約都可獲得1/N的處理機時間。
b時間片的大小對於系統性能有很大的影響。若選擇很小的時間片,將有利於短作業,但意味著會頻繁地執行程序排程和程序上下文的切換,這無疑會增加系統的開銷。反之,若時間片選擇得太長,且為使每個程序都能在一個時間片內完成,RR演算法便退化為FCFS演算法,無法滿足短作業和互動式使用者的需求。
c.程序的切換時機體現出RR演算法的特點。若一個程序在時間片還沒結束時就已完成,此時立即啟用排程程式,將它從執行佇列中刪除。若一個程序在時間片結束時還未執行完畢,則排程程式將把它送往就緒佇列的末尾,等待下一次執行。用C語言程式設計模擬排程程式時,將時間片,程式執行時間量化為整數。此時程式碼
2.優先權排程演算法

a.在時間片演算法中,無法對程序的緊急程度加以區分。而優先順序演算法正好可以解決這一問題。
b.程序優先順序的確定同樣重要。程序優先順序可以分為靜態優先順序和動態優先順序。靜態優先順序是在程序建立初期就被確定的值,此後不再更改。動態優先順序指程序在建立時被賦予一個初值,此後其值會所程序的推進或等待時間的增加而改變。
c.用C語言模擬排程程式時,可用run->prio -= 3; /*優先順序減去三,若設為0則優先順序不變*/ 這條語句控制靜態動態優先順序的切換。
3.程式流程圖 


4.程式程式碼及註釋

    #include <stdio.h>    
    #include <stdlib.h>    
    #include <string.h>    
    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;    
      /*p = ready;*/    
      printf("程序名\t優先順序\t時間片\tcpu時間\t需要時間\t程序狀態\t計數器\n");    
       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;    
      }    
      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;    
      }    
    }    
    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;    
            fst = fst->next;    
          }    

          if(fst ->next == NULL) /*已經搜尋到隊尾,則其優先順序數最小,將其插入到隊尾即可*/    
          {    
            in ->next = fst ->next;    
            fst ->next = in;    
          }    
          else     /*插入到佇列中*/    
          {    
            nxt = in;    
            in ->next = fst;    
          }    
        }    
      }    
    }    
    void InsertTime(PCB *in)  /*將程序插入到就緒佇列尾部*/    
    {    
      PCB *fst;    
      fst = ready;    

      if(ready == NULL)    
      {    
        in->next = ready;    
        ready = in;    
      }    
      else    
      {    
        while(fst->next != NULL)    
        {    
          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(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;  /*假設每個程序所分配的時間片是2*/    
        tmp ->count = 0;    
        InsertTime(tmp);    
      }    
    }    
    void Priority()   /*按照優先順序排程,每次執行一個時間片*/    
    {    
      int flag = 1;    

      GetFirst();    
      while(run != NULL)  /*當就緒佇列不為空時,則排程程序如執行佇列執行*/    
      {    
        Output();  /*輸出每次排程過程中各個節點的狀態*/    
        while(flag)    
        {    
          run->prio -= 0; /*優先順序減去三,若設為0則優先順序不變*/    
          run->cputime++; /*CPU時間片加一*/    
          run->needtime--;/*程序執行完成的剩餘時間減一*/    
          if(run->needtime == 0)/*如果程序執行完畢,將程序狀態置為F,將其插入到完成佇列*/    
          {    
            run ->state = 'F';    
            run->count++; /*程序執行的次數加一*/    
            InsertFinish(run);    
            flag = 0;    
          }    
          else   /*將程序狀態置為W,入就緒佇列*/    
          {    
            run->state = 'W';    
            run->count++; /*程序執行的次數加一*/    
            InsertTime(run);    
            flag = 0;    
          }    
        }    
        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;    
          }    
        }    
        flag = 1;    
        GetFirst();    
      }    
    }   

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
五.程式執行驗證

1.RR演算法 

2.動態優先順序演算法 


3.靜態優先順序演算法 
靜態優先順序演算法僅在一條語句上有區別,執行示意圖類似RR演算法,每個程序按照固定的優先順序(即50減去需要時間)依次執行。
--------------------- 
作者:cyang812 
來源:CSDN 
原文:https://blog.csdn.net/u011303443/article/details/49894303 
版權宣告:本文為博主原創文章,轉載請附上博文連結!