【操作系统】多级反馈队列算法

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

【操作系统】多级反馈队列算法
1. 原理介绍
1. RR时间⽚轮转原理
在采⽤时间⽚轮转算法中,所有的就绪进程按FCFS策略排成⼀个就绪队列。

系统可设置每隔⼀定时间便产⽣⼀次中断,去激活进程调度程序进⾏调度,把CPU分配给队⾸进程,并令其执⾏⼀个时间⽚。

当它运⾏完毕后,⼜把处理机分配给就绪队列中新的队⾸进程,也让它执⾏⼀个时间⽚。

这样,就可以保证就绪队列中的所有进程在确定的时间段内,都能获得⼀个时间⽚的处理机时间。

在RR调度算法中进程的切换,可分为两种情况:①若⼀个时间⽚尚未⽤完,正在运⾏的进程便已经完成,就⽴即激活调度程序,将它从就绪队列中删除,再调度就绪队列中队⾸的进程运⾏,并启动⼀个新的时间⽚。

②在⼀个时间⽚⽤完时,计时器中断处理程序被激活。

如果进程尚未运⾏完毕,调度程序将把它送往就绪队列的末尾。

2.多级反馈队列调度机制
设置多个就绪队列。

在系统中设置多个就绪队列,并为每个队列赋予不同的优先。

第⼀个队列的优先级最⾼,第⼆个次之,其余队列的优先级逐个降低。

该算法为不同列中的进程所赋予的执⾏时间⽚的⼤⼩也各不相同,在优先级愈⾼的队列中,其时间⽚愈⼩。

每个队列都采⽤FCFS算法。

当新进程进⼊内存后,⾸先将它放⼊第⼀队列的末尾,按FCFS原则等待调度。

当轮到该进程执⾏时,如它能在该时间⽚内完成,便可撤离系统。

否则,即它在⼀个时间⽚结束时尚未完成,调度程序将其转⼊第⼆队列的末尾等待调度;如果它在第⼆队列中运⾏个时间⽚后仍未完成,再依次将它放⼊第三队列...依此类推。

当进程最后被降到第n队列后,在第n队列中便采取按RR⽅式运⾏。

按队列优先级调度。

调度程序⾸先调度最⾼优先级队列中的诸进程运⾏,仅当第⼀队列空闲时才调度第⼆队列中的进程运⾏;仅当第1到(i-1)所有队列均空时,才会调度第i队列中的进程运⾏。

如果处理机正在第i队列中为某进程服务时⼜有新进程进⼊任⼀优先级较⾼的队列,此时须⽴即把正在运⾏的进程放回到第i队列的末尾,⽽把处理机分配给新到的⾼优先级进程。

2.设计原理
PCB设计
设计结构体PCB,其中包括进程的标识符,到达时间,服务时间,完成时间,周转时间和带权周转时间。

利⽤动态数组将所有进程存储起来。

1struct PCB
2
3 {
4
5int ID; //标识符
6
7int ComeTime; //到达时间
8
9int ServerTime; //服务时间
10
11int FinishTime; //完成时间
12
13int TurnoverTime; //周转时间
14
15double WeightedTurnoverTime; //带权周转时间
16
17 };
进程就绪队列
采⽤STL中的队列设置3个队列,queue<PCB> Ready[3];
时间⽚由数组timeslice[3]表⽰,⼤⼩分别为2,4,8。

函数模块
主函数模块分为3个模块:读⼊数据函数,多级反馈调度函数,输出函数。

3.流程图
4.代码实现
1 #include <iostream>
2 #include <algorithm>
3 #include <iomanip>
4 #include <vector>
5 #include <queue>
6using namespace std;
7
8//作业结构体
9 typedef struct PCB
10 {
11int ID; //标识符
12int ComeTime; //到达时间
13int ServerTime; //服务时间
14int FinishTime; //完成时间
15int TurnoverTime; //周转时间
16double WeightedTurnoverTime; //带权周转时间 17 }PCB;
18const int QueueNum = 3;//就绪队列长度
19int timeslice[QueueNum];//第⼀个时间⽚
20
21
22
23//输⼊作业信息
24void InputPCB(vector<PCB> &PCBList, int xlice[])
25 {
26
27 cout << "输⼊3个时间⽚⼤⼩: "<<endl;
28for(int i=0;i<3;i++){
29 cin >> timeslice[i];
30 }
31
32while(1) {
33 PCB temp;
34 cout << "输⼊标识符 "<<"到达时间 "<<"服务时间 "<<endl;
35 cin >> temp.ID>> eTime>> temp.ServerTime;
36 temp.FinishTime = 0; //暂时存放运⾏了多少时间,来判断此作业是否运⾏结束
37 PCBList.push_back(temp);
38 cout<<"继续?Y/N:"<<endl;
39char n;
40 cin>>n;
41if(n=='Y'||n=='y')
42continue;
43else
44break;
45
46 }
47 }
48
49
50bool CmpByComeTime(const PCB &p1, const PCB &p2)
51 {
52return eTime < eTime;
53 }
54
55
56//MFQ算法
57void MFQ(vector<PCB> &PCBList, int timeslice[])
58 {
59 sort(PCBList.begin(), PCBList.end(), CmpByComeTime); //按到达时间排序
60 vector<PCB> result; //保存结果
61int BeginTime = (*PCBList.begin()).ComeTime; //第⼀个作业开始时间
62 queue<PCB> Ready[QueueNum]; //设置3个就绪队列
63 Ready[0].push(*PCBList.begin());
64 PCBList.erase(PCBList.begin());
65 cout<<"当前时刻:"<<BeginTime<<" 当前就绪队列:"<<0<<endl;
66 cout<<"第⼀个进程进⼊就绪队列0"<<endl;
67 cout<<endl;
68while (!PCBList.empty())//进程数组不空
69 {
70//这段是为了防⽌前⾯的进程运⾏完了,后⾯的进程还没到,造成死循环
71bool flag = false;
72for (int i = 0; i < QueueNum; ++i)
73 {
74if (!Ready[i].empty())
75 {
76 flag = true;
77break;
78 }
79 }
80if(!flag)
81 {
82 Ready[0].push(*PCBList.begin());
83 PCBList.erase(PCBList.begin());
84 BeginTime = Ready[0].front().ComeTime;
85 }
86
87for (int i = 0; i < QueueNum; ++i)
88 {
89
90if (i != QueueNum - 1) //不是最后⼀个队列
91 {
92while (!Ready[i].empty()) //当前队列不空
93 {
94if (!PCBList.empty() && BeginTime>= (*PCBList.begin()).ComeTime) //有新作业到达,加⼊就绪队列,转到第⼀队列
95 {
96 cout<<"当前时刻:"<<BeginTime<<endl;
97 cout<<"新进程"<<(*PCBList.begin()).ID<<"到达,将其放在第⼀队列尾部"<<endl;
98 cout<<endl;
99 Ready[0].push(*PCBList.begin());
100 PCBList.erase(PCBList.begin());
101 i = 0;
102
103continue;
104 }
105
106if (Ready[i].front().FinishTime + timeslice[i] < Ready[i].front().ServerTime) //时间⽚⽤完没运⾏完,加⼊下⼀队列队尾107 {
108 cout<<"当前时刻:"<<BeginTime+ timeslice[i]<<" 当前就绪队列:"<<i<<endl;
109 cout<<"当前进程"<<Ready[i].front().ID<<"在时间⽚内没有运⾏完,加⼊下⼀个队列尾部!"<<endl;
110 cout<<endl;
111
112 Ready[i].front().FinishTime += timeslice[i] ;
113 Ready[i + 1].push(Ready[i].front());//加⼊下⼀个队列
114 Ready[i].pop();
115 BeginTime += timeslice[i] ;
116 }
117else//此作业运⾏完
118 {
119 BeginTime += Ready[i].front().ServerTime - Ready[i].front().FinishTime;
120 Ready[i].front().FinishTime = BeginTime;
121 Ready[i].front().TurnoverTime = Ready[i].front().FinishTime - Ready[i].front().ComeTime;
122 Ready[i].front().WeightedTurnoverTime = (double)Ready[i].front().TurnoverTime / Ready[i].front().ServerTime;
123 cout<<"当前时刻:"<<BeginTime<<" 当前就绪队列:"<<i<<endl;
124 cout<<"当前进程"<< Ready[i].front().ID<<"在时间⽚内运⾏完!"<<endl;
125 cout<<endl;
126//从就绪队列中移除作业
127 result.push_back(Ready[i].front());
128 Ready[i].pop();
129 }
130 }
131 }
132else
133 {
134while (!Ready[i].empty())
135 {
136if (!PCBList.empty() && BeginTime >= (*PCBList.begin()).ComeTime) //有新作业到达,加⼊就绪队列,转到第⼀队列
137 {
138 cout<<"当前时刻:"<<BeginTime<<endl;
139 cout<<"新进程"<<(*PCBList.begin()).ID<<"到达,将其放在最后队列尾部"<<endl;
140 cout<<endl;
141 Ready[0].push(*PCBList.begin());
142 PCBList.erase(PCBList.begin());
143 i = -1;
144break;
145 }
146if (Ready[i].front().FinishTime + timeslice[i] < Ready[i].front().ServerTime) //时间⽚⽤完没运⾏完,加⼊队尾
147 { cout<<"当前时刻:"<<BeginTime+ timeslice[i]<<" 当前就绪队列:"<<i<<endl;
148 cout<<"当前进程"<<Ready[i].front().ID<<"在时间⽚内没有运⾏完,加⼊该队列尾部!"<<endl;
149 cout<<endl;
150 Ready[i].front().FinishTime += timeslice[i] ;
151 Ready[i].push(Ready[i].front());
152 Ready[i].pop();
153 BeginTime += timeslice[i] ;
154 }
155else//此作业运⾏完
156 {
157 BeginTime += Ready[i].front().ServerTime - Ready[i].front().FinishTime;
158 Ready[i].front().FinishTime = BeginTime;
159 Ready[i].front().TurnoverTime = Ready[i].front().FinishTime - Ready[i].front().ComeTime;
160 Ready[i].front().WeightedTurnoverTime = (double)Ready[i].front().TurnoverTime / Ready[i].front().ServerTime;
161 cout<<"当前时刻:"<<BeginTime<<" 当前就绪队列:"<<i<<endl;
162 cout<<"当前进程"<< Ready[i].front().ID<<"在时间⽚内运⾏完!"<<endl;
163 cout<<endl;
164//从就绪队列中移除作业
165 result.push_back(Ready[i].front());
166 Ready[i].pop();
167 }
168 }
169 }
170 }
171 }
172
173//按ComeTime升序排序,便于显⽰结果
174 PCBList = result;
175 sort(PCBList.begin(), PCBList.end(), CmpByComeTime);
176 }
177
178//显⽰结果
179void show(vector<PCB> &PCBList)
180 {
181int SumTurnoverTime = 0;
182double SumWeightedTurnoverTime = 0;
183
184 cout<<"标识符 "<<"达到时间 "<<"服务时间 "<<"完成时间 "<<"周转时间 "<<"带权周转时间" <<endl;
185
186for (vector<PCB>::iterator it = PCBList.begin(); it < PCBList.end(); ++it){
187 cout<<(*it).ID<<""<<(*it).ComeTime<<""<< (*it).ServerTime<<""<<(*it).FinishTime<<""<<(*it).TurnoverTime<<""<< (*it).WeightedTurnoverTime<<endl; 188 SumTurnoverTime+=(*it).TurnoverTime;
189 SumWeightedTurnoverTime+=(*it).WeightedTurnoverTime;
190 }
191
192 cout << "平均周转时间: " << (double)SumTurnoverTime / PCBList.size() << endl;
193 cout << "平均带权周转时间: " << SumWeightedTurnoverTime / PCBList.size() << endl;
194 }
195
196//⽐较函数,按ComeTime升序排列
197
198
199
200int main()
201 {
202 vector<PCB> PCBList;//动态数组存放进程
203
204 InputPCB(PCBList, timeslice);//输⼊时间⽚⼤⼩,作业信息
205
206 MFQ(PCBList, timeslice);
207
208 show(PCBList);//显⽰结果
209
210return0;
211 }
212
5.实例测试
结果分析:
如图5所⽰,0时刻,1进程到达,运⾏1个时间⽚2,此时进程没有运⾏完,加⼊下⼀队列,进程2到达,转到队列0调度进程2,运⾏1个时间⽚2,进⼊队列1队尾等待。

时刻4开始,第⼀队列为空,此时调度第⼆队列,在进程1运⾏1个时间⽚4,没有运⾏完,加⼊队列2。

时刻8,进程3到达,加⼊到第⼀队列尾部,调度进程3,进程3运⾏1个时间⽚2之后,加⼊下⼀队列。

时刻10,队列1中进程2开始运⾏,时刻12运⾏结束。

删除进程2.进程3开始运⾏,当前时间⽚内运⾏不完,加到队列2队尾。

时刻16,进⼊队列2,调度进程1进⾏运⾏,时刻20,进程1运⾏结束,删除进程1。

运⾏进程3,在当前时间⽚下不能运⾏完,则加⼊队列2。

时刻28,进⼊队列2,调度进程3,时刻29运⾏完毕。

相关文档
最新文档