1、设置 N 个就绪进程队列,即队列 0,队列 1,……,队列 N-1,用于存放就绪进程。每个队列
优先级不同,且从队列 0 到队列 N-1,优先级依次递减。
2、不同队列中的进程所赋予的时间片长度不同;优先级越低,时间片越长,比如,队列 0 中进程
的时间片为 5,队列 1 中进程的时间片为 10 等等。
3、在队列内部,进程之间采用先来先服务(FCFS)算法辅以时间片限时机制进行调度:位于队
列头部的进程(队首进程)先执行,如果在时间片限时内,它执行结束,则从本级队列移除;如
果它时间片内未能运行结束,则将它移入下一级队列末尾(若本级队列是最低优先级队列,则移
入本级队列末尾),然后按它当前所在新队列给它分配新的时间片。
4、当进程到达内存后,进入队列 0 末尾,并给它分配队列 0 规定的时间片。
5、优先执行高优先级队列中的队首进程,若高优先级队列中没有就绪进程,则执行下一级优先级
队列中的队首进程。
6、正在执行低优先级队列中的队首进程时,有新的进程到达高优先级队列,则立即中断低优先级
进程,并切换到高优先级进程执行。
!和书上的实现稍有不同!
结构体:
struct SPCB
{
int pid; // 进程号
int arrivalTime; // 到达时间
int workTime; // 服务时间
int remainingTime; // 剩余服务时间
int timeSlice; // 剩余时间片
int startTime; // 开始时间。必要时,可在 mfqSchedule 函数中使用,用于记录进程开始执行的时间
int endTime; // 进程完成服务的时间。必要时,可在 mfqSchedule 函数中使用,用于记录进程完成服务的时间
};
主函数:
int main()
{
int m, n; // m 为队列数量,n 为进程数量
int i;
cin >> m >> n; // 输入队列数量和进程数量
vector<int> timeSlice(m); // t 为整型数组,存放 m 级队列的时间片长度
vector<SPCB> pcb(n);
for (i = 0; i < m; i++)
{
cin >> timeSlice[i]; // 输入 m 级队列的时间片长度;一般来说,后一级队列的时间片长度大于前一级,比如,后一级时间片长度是前一级的 2 倍
}
for (i = 0; i < n; i++)
{
cin >> pcb[i].arrivalTime; // 输入第 i 个进程的到达时间
cin >> pcb[i].workTime; // 输入第 i 个进程的服务时间
pcb[i].pid = i; // 第 i 个进程的进程号取为 i
pcb[i].remainingTime = pcb[i].workTime; // 剩余服务时间初始化为服务时间
pcb[i].timeSlice = timeSlice[0]; // 剩余时间片初始化为最高优先级队列的时间片长度
pcb[i].startTime = -1; // 开始时间初始化为 -1,表示此时开始时间记录是无效值
}
mfqSchedule(pcb, timeSlice);
/*
for (int ii = 0; ii < (); ii++)
{
cout << endl;
cout <<"进程"<<ii<<endl<<"进程开始时间:"<< pcb[ii].startTime << " " <<"进程结束时间:"<< pcb[ii].endTime << endl;
}
*/
return 0;
}
多级反馈队列函数实现:
void mfqSchedule(vector<SPCB> &pcb, const vector<int> &timeSlice)
{
int i1 = 0;
int t = ();
int flag=0;//退出主循环条件
vector<vector<SPCB>> a;
(t);//定义队列大小
//int flag = 0;//判断是否有在低优先级的时候有进程插入如果有置为1
for (i1; i1 < 1000; i1++)//主要循环
{
//对队列中的进程操作
int i3 = 0;
for (i3; i3 < (int)t; i3++)
{
if(a[i3].empty())
{
}
else
{
if (a[i3].front().remainingTime == a[i3].front().workTime)
{
pcb[a[i3].front().pid].startTime = i1-1;//开始时间
}
a[i3].front().remainingTime--;
a[i3].front().timeSlice--;
if (a[i3].front().remainingTime == 0)//进程pid1结束
{
int pid1 = a[i3].front().pid;
pcb[pid1].endTime = i1;//结束时间
a[i3].erase(a[i3].begin());//删除开头
if (a[i3].empty())
break;
}
if (a[i3].front().timeSlice == 0)//进程在时间片完还未结束
{
if (i3 == t - 1)//如果是优先级最低队列,则放到此队列末尾
{
a[i3].front().timeSlice = timeSlice[i3];//重置剩余时间片
a[i3].push_back(a[i3].front());
a[i3].erase(a[i3].begin());
}
else//如果不是优先级最高的队列,则放入更低优先级队列末尾
{
a[i3].front().timeSlice = timeSlice[i3 + 1];//重置剩余时间片
a[i3 + 1].push_back(a[i3].front());
a[i3].erase(a[i3].begin());
}
}
break;
}
}
//判断是否有进程需要插入,有则放入队列0末尾
int i2 = 0;
for (i2; i2 < (); i2++)
{
if (pcb[i2].arrivalTime == i1)
{
a[0].push_back(pcb[i2]);
//pcb[i2].startTime = i1;//开始时间
flag++;
}
}
}
//输出平均周转时间
float sum=0;
int i0 = 0;
for (i0; i0 < (int)(); i0++)
{
sum += pcb[i0].endTime - pcb[i0].arrivalTime;
}
sum=sum / (());
printf("%.3f", sum);
cout << endl;
//输出平均带权周转时间
float sum1 = 0;
int i00 = 0;
for (i00; i00 < (int)(); i00++)
{
//sum1 += (float)(pcb[i00].endTime - pcb[i00].arrivalTime)/(pcb[i00].endTime - pcb[i00].startTime);
sum1 += (float)(pcb[i00].endTime - pcb[i00].arrivalTime) / pcb[i00].workTime;
}
sum1 = sum1 / (());
printf("%.3f", sum1);
}
主循环只有1000次,也没有设置退出循环的条件。可以自己改动。
小旻