進程調度算法spf,fpf,時間片輪轉算法實現


調度的基本概念:從就緒隊列中按照一定的算法選擇一個進程並將處理機分配給它運行,以實現進程並發地執行。

進程信息

1 struct node {
2     string name;//進程名稱
3     int id;//進程id
4     int time;//進程服務時間
5     int rtime;//進程服務時間(主要用於時間片輪轉算法)
6     int level;//進程優先級
7     int start;//進程提交時間
8     int lst;//進程調度時間
9 };
1 set<string> pname;//存放進程名稱,防止創建重復進程
2 queue<node> qq;//時間片輪轉時用到的就緒隊列
3 queue<node> pp;//進程的執行隊列
4 queue<node> db;//時間片算法中的調度順序
5 priority_queue<node, vector<node>, cmpspf> spf;//短時間優先算法隊列
6 priority_queue<node, vector<node>, cmpfpf> fpf;//優先級算法隊列
7 vector<node> ready;//就緒隊列
8 vector<node> emy;//已刪除的進程

 

用vector容器存放就緒的進程(每插入一個,sort一下,依據進程提交時間升序排列)

spf(短作業優先算法)

算法思想:服務時間短的進程在就緒隊列前面。

算法規則:要求服務時間最短的進程/作業優先得到服務。

算法實現:模擬時間,將已提交的進程插入優先隊列,在依據時間是否到達完成時間來判斷哪個進程被移入內存中運行

代碼:

 1 struct cmpspf {
 2     bool operator() (node a, node b) {
 3         if (a.time == b.time)return a.start > b.start;
 4         return a.time > b.time;
 5     }
 6 };
 7 
 8     int j = 0, num = ready.size(),ok=1;
 9     sum = -1, ans = 0, avg = 0.00;
10     //sum作為在執行進程的完成時間
11     if (t == 1) {
12         for(int i=0;i<=100000;i++) {
13             if (i == sum) {//首先判斷是否到達在執行進程的完成時間
14                 node temp;
15                 temp = spf.top(); spf.pop();
16                 temp.lst = i - temp.start;//計算周轉時間
17                 ans += temp.lst;//總的周轉時間
18                 avg += double(temp.lst) / double(temp.time);//總的帶權周轉時間
19                 pp.push(temp);//執行完畢的進程放入執行隊列
20                 if (!spf.empty())sum += spf.top().time;
21             }            
22             while (j < num && i == ready[j].start) {//將到達進程提交時間的進程放入就緒隊列
23                 spf.push(ready[j]);
24                 //當CPU執行過程中出現空閑時,更新sum值
25                 if (i > sum&&sum<=spf.top().start)sum = spf.top().start + spf.top().time;
26                 j++;
27             }
28             if (ok&&!spf.empty()) {//第一個執行的進程的完成時間
29                 sum = i + spf.top().time;
30                 ok = 0;
31             }
32             if (j == num && spf.empty())break;//所有進程執行完畢
33         }
        
34 printf("進程 周轉時間 帶權周轉時間\n"); 35 while (!pp.empty()) { 36 node out; 37 out = pp.front(); pp.pop(); 38 cout << out.name; 39 printf(" %d %.2f\n", out.lst, double(out.lst) / double(out.time)); 40 } 41 printf("平均周轉時間為:%.2f\n", double(ans) / double(num)); 42 printf("平均帶權周轉時間為%.2f\n", avg);

 

fpf(優先級調度算法)

算法思想:進程優先級高的進程在就緒隊列前面。

算法規則:要求進程優先級高的進程/作業優先得到服務。

算法實現:模擬時間,將已提交的進程插入優先隊列,在依據時間是否到達完成時間來判斷哪個進程被移入內存中運行

代碼:邏輯跟spf算法是一樣的這里不過多敘述。

1 //spf、fpf的區別就在於優先隊列中的規則不同
2 struct cmpfpf {
3     bool operator() (node a, node b) {
4         if (a.level == b.level)return a.start > b.start;
5         return a.level < b.level;
6     }
7 };
for(int i=0;i<=10000;i++) {
    if (i == sum) {
        node temp;
        temp = fpf.top(); fpf.pop();
        temp.lst = i - temp.start;
        ans += temp.lst;
        avg += double(temp.lst) / double(temp.time);
        pp.push(temp);
        if (!fpf.empty())sum += fpf.top().time;
    }
    while (j < num && i == ready[j].start) {
        fpf.push(ready[j]);
        if (i > sum&&sum<=fpf.top().start)sum =     
                fpf.top().start + fpf.top().time;
        j++;
    }
    if (ok&&!fpf.empty()) {
        sum = i + fpf.top().time;
        ok = 0;
    }
    if (j == num && fpf.empty())break;
}
    printf("進程           周轉時間      帶權周轉時間\n");
    while (!pp.empty()) {
        node out;
        out = pp.front(); pp.pop();
        cout << out.name;
        printf("             %d             %.2f\n", out.lst,     
                double(out.lst) / double(out.time));
    }
    printf("平均周轉時間為:%.2f\n", double(ans) /double(num));
    printf("平均帶權周轉時間為%.2f\n", avg);    

時間片輪轉算法

算法思想:公平的、輪流的為各個進程服務,讓每個進程在一定時間間隔內都可以得到響應

算法規則:系統根據FCFS策略,將所有的就緒進程排成一個就緒隊列。

輪流讓各個進程執行一個時間片的,若進程未在一個時間片內執行完,則被剝奪處理機,將進程放到就緒隊列隊尾重新排隊。

算法實現:利用隊列模擬就緒隊列,模擬時間,每次時間增加一個時間片長度,先判斷是否有進程在時間片內結束,如果有的話,就對時間進行修改回退到剛完成進程的時間,再判斷時間片內是否有進程提交,有的話加入隊列。

代碼

 1 printf("請設置時間片大小:\n");
 2 sf(m);
 3 for (int i = 0; i <= 100000; i += m) {//每次自增一個時間片
 4     if (!qq.empty()) {//當運行隊列有進程時,則運行該進程
 5         node temp;
 6         temp = qq.front(); qq.pop();
 7                 db.push(temp);
 8         if (temp.time > m) {//若進程不能在該時間片內運行完畢,則將服務時間減去時間片,再重新放入隊列,這也是使用rtime計算帶權周轉時間的原因
 9             temp.time -= m;
10             qq.push(temp);
11         }
12         else {//反之回退時間,並將已完成的進程放入執行完畢隊列
13             i =i- m + temp.time;
14             temp.lst = i - temp.start;
15             ans += temp.lst;
16             pp.push(temp);
17         }
18     }
19     while (j < num && i >= ready[j].start) {//到達時間片的進程放入隊列
20         if (ok||qq.empty()) {
21             i = ready[j].start;
22             ok = 0;
23         }
24         ready[j].rtime = ready[j].time;
25         qq.push(ready[j]);
26         j++;
27     }
28     if (j == num && qq.empty())break;
29 }
30 printf("進程調度順序:\n");
31 while(!db.empty()){cout<<db.front().name<<" ";db.pop();}
32 printf("\n進程執行完畢順序           周轉時間      帶權周轉時間\n");
33 while (!pp.empty()) {
34     node out;
35     out = pp.front(); pp.pop();
36     cout << out.name;
37     printf("             %d             %.2f\n", out.lst, double(out.lst) / double(out.rtime));
38     avg += double(out.lst) / double(out.rtime);
39 }
40 printf("平均周轉時間%.2f\n", double(ans) / double(num));
41 printf("平均帶權周轉時間為%.2f\n", avg/double(num)); 

總代碼如下:

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 typedef long long LL;
  4 typedef vector<int> vi;
  5 typedef pair<int, int> ii;
  6 #define inf 1e9
  7 #define F first
  8 #define S second
  9 #define dbg(x) cout<<#x<<" value : "<<x<<"\n";
 10 #define rep(i,j,k) for(int i = (j); i <= (k); i++)
 11 #define rep__(i,j,k) for(int i = (j); i < (k); i++)
 12 #define per(i,j,k) for(int i = (j); i >= (k); i--)
 13 #define per__(i,j,k) for(int i = (j); i > (k); i--)
 14 #define mst(a,b) memset(a,b,sizeof(a))
 15 #define sf(n) scanf_s("%d",&n)
 16 #define stf(n,m) scanf("%d%d",&n,&m)
 17 #define pf(n) printf("%d\n",n)
 18 #define slf(n) scanf("%lld",&n)
 19 #define plf(n) printf("%lld\n",n)
 20 const int N = 1e3 + 10;
 21 priority_queue<int, vector<int>, less<int> > q;
 22 int t, x, sum, ans, m;
 23 double avg;
 24 string k;
 25 struct node {
 26     string name;//進程名稱
 27     int id;//進程id
 28     int time;//進程服務時間
 29     int rtime;//進程服務時間(主要用於時間片輪轉算法)
 30     int level;//進程優先級
 31     int start;//進程提交時間
 32     int lst;//進程調度時間
 33 };
 34 struct cmpspf {
 35     bool operator() (node a, node b) {
 36         if (a.time == b.time)return a.start > b.start;
 37         return a.time > b.time;
 38     }
 39 };
 40 struct cmpfpf {
 41     bool operator() (node a, node b) {
 42         if (a.level == b.level)return a.start > b.start;
 43         return a.level < b.level;
 44     }
 45 };
 46 set<string> pname;//存放進程名稱,防止創建重復進程
 47 queue<node> qq;//時間片輪轉時用到的就緒隊列
 48 queue<node> pp;//進程的執行隊列
 49 queue<node> db;//時間片算法中的調度順序
 50 priority_queue<node, vector<node>, cmpspf> spf;//短時間優先算法隊列
 51 priority_queue<node, vector<node>, cmpfpf> fpf;//優先級算法隊列
 52 vector<node> ready;//就緒隊列
 53 vector<node> emy;//已刪除的進程
 54 bool cmp(const node& a, const node& b) {
 55     return a.start < b.start;
 56 }
 57 void create() {
 58     node a;
 59     printf("請輸入新進程的名稱:\n");
 60     cin >> a.name;
 61     if (pname.find(a.name) != pname.end()) {
 62         printf("進程已存在,請從新輸入:\n");
 63         create();
 64         return;
 65     }
 66     pname.insert(a.name);
 67     printf("請輸入新進程的到達時間、服務時間:\n");
 68     sf(a.start);sf(a.time);
 69     printf("請輸入新進程的PID:\n");sf(a.id);
 70     printf("請輸入新進程的優先級:\n");sf(a.level);
 71     ready.push_back(a);
 72     sort(ready.begin(), ready.end(), cmp);
 73 }
 74 void kill() {
 75     node b;
 76     printf("請輸入要終止的進程名字\n");
 77     cin >> k;
 78     if (pname.find(k) != pname.end()) {
 79         int num = ready.size();
 80         for (int i = 0; i < num; i++) {
 81             if (ready[i].name == k) {
 82                 b = ready[i];
 83                 emy.push_back(b);
 84                 ready.erase(ready.begin() + i);
 85                 printf("終止進程成功!\n");
 86             }
 87             if (num == ready.size()) {
 88                 printf("該進程已在空隊列中!\n");
 89             }
 90         }
 91     }
 92     else {
 93         printf("該進程不存在,請輸入正確的進程名!\n");
 94         kill();
 95         return;
 96     }
 97 }
 98 void display() {
 99     while (!pp.empty())pp.pop();
100     while (!spf.empty())spf.pop();
101     while (!fpf.empty())fpf.pop();
102     while (!qq.empty())qq.pop();
103     if (ready.empty()) {
104         printf("就緒隊列為空!\n");
105         return;
106     }
107     printf("請選擇調度算法\n");
108     printf("1、spf調度算法\n");
109     printf("2、fpf調度算法\n");
110     printf("3、時間片輪轉算法\n");
111     printf("4、返回菜單\n");
112     sf(t);
113     int j = 0, num = ready.size(),ok=1;
114     sum = -1, ans = 0, avg = 0.00;
115     //sum作為在執行進程的完成時間
116     if (t == 1) {
117         rep(i, 0, 100000) {
118             if (i == sum) {//首先判斷是否到達在執行進程的完成時間
119                 node temp;
120                 temp = spf.top(); spf.pop();
121                 temp.lst = i - temp.start;//計算周轉時間
122                 ans += temp.lst;//總的周轉時間
123                 avg += double(temp.lst) / double(temp.time);//總的帶權周轉時間
124                 pp.push(temp);
125                 if (!spf.empty())sum += spf.top().time;
126             }            
127             while (j < num && i == ready[j].start) {//將到達進程提交時間的進程放入就緒隊列
128                 spf.push(ready[j]);
129                 //當CPU執行過程中出現空閑時,更新sum值
130                 if (i > sum&&sum<=spf.top().start)sum = spf.top().start + spf.top().time;
131                 j++;
132             }
133             if (ok&&!spf.empty()) {//第一個執行的進程的完成時間
134                 sum = i + spf.top().time;
135                 ok = 0;
136             }
137             if (j == num && spf.empty())break;//所有進程執行完畢
138         }
139         printf("進程           周轉時間      帶權周轉時間\n");
140         while (!pp.empty()) {
141             node out;
142             out = pp.front(); pp.pop();
143             cout << out.name;
144             printf("             %d             %.2f\n", out.lst, double(out.lst) / double(out.time));
145         }
146         printf("平均周轉時間為:%.2f\n", double(ans) / double(num));
147         printf("平均帶權周轉時間為%.2f\n", avg);
148     }
149     else if (t == 2) {
150         rep(i, 0, 100000) {
151             if (i == sum) {
152                 node temp;
153                 temp = fpf.top(); fpf.pop();
154                 temp.lst = i - temp.start;
155                 ans += temp.lst;
156                 avg += double(temp.lst) / double(temp.time);
157                 pp.push(temp);
158                 if (!fpf.empty())sum += fpf.top().time;
159             }
160             while (j < num && i == ready[j].start) {
161                 fpf.push(ready[j]);
162                 if (i > sum&&sum<=fpf.top().start)sum = fpf.top().start + fpf.top().time;
163                 j++;
164             }
165             if (ok&&!fpf.empty()) {
166                 sum = i + fpf.top().time;
167                 ok = 0;
168             }
169             if (j == num && fpf.empty())break;
170         }
171         printf("進程           周轉時間      帶權周轉時間\n");
172         while (!pp.empty()) {
173             node out;
174             out = pp.front(); pp.pop();
175             cout << out.name;
176             printf("             %d             %.2f\n", out.lst, double(out.lst) / double(out.time));
177         }
178         printf("平均周轉時間為:%.2f\n", double(ans) / double(num));
179         printf("平均帶權周轉時間為%.2f\n", avg);
180     }
181     else if (t == 3) {
182         printf("請設置時間片大小:\n");
183         sf(m);
184         for (int i = 0; i <= 100000; i += m) {//每次自增一個時間片
185             if (!qq.empty()) {//當運行隊列有進程時,則運行該進程
186                 node temp;
187                 temp = qq.front(); qq.pop();
188                 db.push(temp);
189                 if (temp.time > m) {//若進程不能在該時間片內運行完畢,則將服務時間減去時間片,再重新放入隊列,這也是使用rtime計算帶權周轉時間的原因
190                     temp.time -= m;
191                     qq.push(temp);
192                 }
193                 else {//反之回退時間,並將已完成的進程放入執行完畢隊列
194                     i =i- m + temp.time;
195                     temp.lst = i - temp.start;
196                     ans += temp.lst;
197                     pp.push(temp);
198                 }
199             }
200             while (j < num && i >= ready[j].start) {//到達時間片的進程放入隊列
201                 if (ok||qq.empty()) {
202                     i = ready[j].start;
203                     ok = 0;
204                 }
205                 ready[j].rtime = ready[j].time;
206                 qq.push(ready[j]);
207                 j++;
208             }
209             if (j == num && qq.empty())break;
210         }
211         printf("進程調度順序:\n");
212         while (!db.empty()) { cout << db.front().name << " "; db.pop(); }
213         printf("\n進程執行完畢順序           周轉時間      帶權周轉時間\n");
214         printf("進程           周轉時間      帶權周轉時間\n");
215         while (!pp.empty()) {
216             node out;
217             out = pp.front(); pp.pop();
218             cout << out.name;
219             printf("             %d             %.2f\n", out.lst, double(out.lst) / double(out.rtime));
220             avg += double(out.lst) / double(out.rtime);
221         }
222         printf("平均周轉時間%.2f\n", double(ans) / double(num));
223         printf("平均帶權周轉時間為%.2f\n", avg/double(num));
224     }
225     else if (t == 4) {
226         return;
227     }
228     else {
229         printf("輸入有誤,請按照提示輸入:\n");
230         display();
231         return;
232     }
233 }
234 inline void meun() {
235     printf("******************菜單************************\n\n");
236     printf("**********      1、輸入進程    ***************\n");
237     printf("**********      2、輸出隊列    ***************\n");
238     printf("**********      3、終止進程    ***************\n");
239     printf("**********      4、退出程序    ***************\n");
240 }
241 void solve() {
242     while (1) {
243         meun();
244         sf(x);
245         switch (x) {
246         case 1:
247             create();
248             break;
249         case 2:
250             display();
251             break;
252         case 3:
253             kill();
254             break;
255         case 4:
256             return;
257         default:
258             printf("請按照提示信息進行輸入\n");
259             break;
260         }
261     }
262     return;
263 }
264 
265 int main()
266 {
267     solve();
268     return 0;
269 }
View Code

可以補充的地方,阻塞進程,加入新的vector,每阻塞一個進程,就將其在ready中刪除放入新的vector中,喚醒時在阻塞隊列中找到該進程,將其移回ready隊列。

其實代碼寫的不是很漂亮,懶省事用了stl,沒寫鏈表,時間也是模擬出來的跟真實情況有很大差別,實現的效率也不高(進程少了還行,多了就挺耗時間的,草率地說是O(log(n!)的算法)。這次代碼實現的三種算法都是非搶占式的算法,實際情況要比這復雜的多,代碼僅供參考,歡迎大家提意見。

優點就是容易想,算是非常暴力的模擬了;能隨便加進程,不斷更新調度順序。以后看情況會把程序給完善完善。


免責聲明!

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



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