通过C++编程来模拟三种进程调度方式:FCFS(先来先服务),Priority Scheduling(优先度调度)和Multilever feedback queue (多级反馈队列)
现有5个进程同时一次进入进程调度器
进程名 | 时间花销 | 优先度 |
P1 | 10 | 3 |
P2 | 1 | 1 |
P3 | 2 | 3 |
P4 | 1 | 4 |
P5 | 5 | 2 |
多级反馈队列中,第一级的时间片是1,第二级是2.....以此类推
模拟进程调度程序说明
两个结构
首先介绍两个数据结构
Process结构:
structProcess
{
char name[NAME_LENGTH];//进程名字
int priority;//优先度
int cost;//进程执行需要时间开销
int used;//已用时间
int wait_time;//等待时间
Process(char na[],int ct,int prio)
{
strcpy(name,na);
cost = ct;
priority = prio;
wait_time = 0;
used = 0;
}
void print()
{
printf("Process Name:%s \tPriorityValue:%d \tWaiting time:%d\n",name,priority,wait_time);
}
};
这个结构用来保存进程信息。
然后通过创建一个Process指针数组来保存要处理的进程
Process *process_list[PROCESS_NUM];
process_list[0]=newProcess("P1",10,3);
process_list[1]=newProcess("P2",1,1);
process_list[2]=newProcess("P3",2,3);
process_list[3]=newProcess("P4",1,4);
process_list[4]=new Process("P5",5,2);
MultiQueue结构:
struct MultiQueue
{
queue<Process *> plist;//该级的队列
int quantum_time;//该级别的时间片
int lever;//记录级别
MultiQueue *next;//下一级队列
MultiQueue()
{
lever = 0;
next = NULL;
quantum_time = 0;
while(!plist.empty())
plist.pop();
}
};
这个多级队列结构是服务于多级反馈队列进程调度服务的。
一个MultiQueue就是一个多级反馈队列。
quantum_time定义了该级别的时间片
plist则是保存了在这个级别队列里面的待运行进程
lever记录当前是第几个级别的
三个方法
由于要模拟先到先服务(FIFO/FCFS)、优先数调度(Priority Scheduling)和多级反馈队列调度(Multilevel feedback queue),所以我实现了三个方法分别表示这三种调度方法,每一个方法的参数都是待调度进程数组和数组规模。也就是上文利用Process创建的指针数组Process *process_list[PROCESS_NUM].
First Come,First Served方法
//First Come,First Served 先来先服务 ,即FIFO,First In,First Out
void FCFS(Process* plist[],int psize)
{
printf("First Come First Served running...\n");
queue< Process * > fcfs_list;
while(!fcfs_list.empty())fcfs_list.pop();
for (int i=0;i<psize;i++)
{
fcfs_list.push(plist[i]);
}
int time =0;
while(!fcfs_list.empty())
{
Process * excu = fcfs_list.front();
fcfs_list.pop();
excu->wait_time = time;
time += excu->cost;
printf("%s excute %d timeunits...\n",excu->name,excu->cost);
}
printf("First Come First Served ending...\n");
time = 0;
for (int i=0;i<psize;i++)
{
plist[i]->print();
time += plist[i]->wait_time;
}
double mwt = (double)time/psize;
printf("Mean Waiting Time is %.2lf\n",mwt);
printf("------------------------\n");
}
首先创建一个队列fcfs_list表示FCFS的待执行进程。然后按照plist[]的顺序把进程压进fcfs_list里面。接着就开始执行进程。
每次执行从fcfs_list取出最前面的进程,此时时间累加器time即为此进程的等待时间,并把该进程的执行时间累加紧time里面。一直执行直到fcfs_list为空。
这时每一个进程任务都已经执行完毕了,最后可以通过访问每一个进程的plist[i]->wait_time来得到平均等待时间并打印出来
Priority Scheduling方法
//Priority Scheduling优先数调度法,非抢占式
void PS(Process* plist[],int psize)
{
printf("Priority Scheduling running...\n");
//因为优先度调度需要根据优先度对进程进行排序后放进队列,为了不影响原顺序,用一个新的数组来暂存排序结果
Process* sort_list[PROCESS_NUM];
for (int i=0;i<psize;i++)
{
sort_list[i] = plist[i];
}
sort_priority(sort_list,psize);
queue< Process * > ps_list;
while(!ps_list.empty())
ps_list.pop();
for (int i=0;i<psize;i++)
{
ps_list.push(sort_list[i]);
}
int time =0;
while(!ps_list.empty())
{
Process * excu = ps_list.front();
ps_list.pop();
excu->wait_time = time;
time += excu->cost;
printf("%s excute %d timeunits...\n",excu->name,excu->cost);
}
printf("Priority Scheduling ending...\n");
time = 0;
for (int i=0;i<psize;i++)
{
plist[i]->print();
time += plist[i]->wait_time;
}
double mwt = (double)time/psize;
printf("Mean Waiting Time is %.2lf\n",mwt);
printf("------------------------\n");
}
由于优先数调度是根据每一个进程的优先数来判定进程的执行顺序,优先数越小,越早执行。
所以要先对进程进行一个优先数升序排序。为了不影响原进程数组的顺序。这里新建了一个plist[]的副本sort_list[],然后对sort_list[]进行升序排序,最后把sort_list[]排序后的结果按顺序压进优先数调度队列ps_list里面。
接着就开始执行进程。
每次执行从ps_list取出最前面的进程,此时时间累加器time即为此进程的等待时间,并把该进程的执行时间累加紧time里面。一直执行直到ps_list为空。
这时每一个进程任务都已经执行完毕了,最后可以通过访问每一个进程的plist[i]->wait_time来得到平均等待时间并打印出来
Multilevel feedback queue方法
//Multilevel feedback queue多级反馈队列调度
void MFQ(Process* plist[],int psize)
{
printf("Multilevel feedback queue running...\n");
MultiQueue *mq = new MultiQueue();
MultiQueue *current;
mq->quantum_time = 1;
mq->lever = 1;
for (int i=0;i<psize;i++)
{
plist[i]->used = 0;
mq->plist.push(plist[i]);
}
int time = 0;
current = mq;
//只有没有下一级队列并且当前队列为空时,才退出
while(! (current->plist.empty() && current->next==NULL))
{
if (current->plist.empty())
current = current->next;
else
{
Process * excu = current->plist.front();
current->plist.pop();
int todo_time = excu->cost - excu->used;
if (todo_time > current->quantum_time )
{
todo_time =current->quantum_time;
excu->used += todo_time;
if (current->next==NULL)
{
current->next = newMultiQueue();
current->next->quantum_time = current->quantum_time+1;
current->next->lever= current->lever+1;
}
current->next->plist.push(excu);
}else
{
excu->wait_time = time -excu->used;
excu->used += todo_time;
}
time += todo_time;
printf("%s excute %d time units at %dlayer...\n",excu->name,todo_time,current->lever);
}
}
printf("Multilevel feedback queue ending...\n");
time = 0;
for (int i=0;i<psize;i++)
{
plist[i]->print();
time += plist[i]->wait_time;
}
double mwt = (double)time/psize;
printf("Mean Waiting Time is %.2lf\n",mwt);
printf("------------------------\n");
}
多级反馈队列把进程划分到多个级别里面执行,每一个级别的队列给与进程有限的运行时间,若所给时间内还没有执行完毕,则弹出此进程并把此进程放置到下一级进程里面继续执行。
而一般下一级队列要比上一级队列的能给与时间片要长。也就是说,如果第一级队列的时间片为1,时间片时间内不能完成,则弹到第二级队列执行,第二级的队列时间片可能就为2,以此类推。
在MFQ方法里面也是这么运作的。首先创建一个多级队列MultiQueue *mq = new MultiQueue(),用MultiQueue *current指示当前级别队列。一开始把所有进程压进mq->plist里面,也就是压进第一级的队列里面。然后开始执行进程
每执行一个进程,首先判断该进程还需要执行的时间能否在当前级别的时间片内完成,能完成则该进程的等待时间为excu-> wait_time = 当前时间time-该进程已用时间excu->used ;若是不能在该时间片内完成,则把此进程使用世家加上该级别的时间片世家todo_time = current->quantum_time;excu->used += todo_time;由于此进程仍需要执行,需要压进下一级的队列里面待执行,所以先检查下一级队列是否存在,不存在则创建下一级队列,然后压进下一级队列里面。
以上操作完成了就表示该进程在此级别里面的操作结束了。把该进程的使用时间todo_time 加到时间累加器time里面表示时间的使用time += todo_time;
一直重复这操作直到该级别的队列为空。若是下一级别队列不为空,则把当前队列指针移到下一级队列里面if (current->plist.empty()) current = current->next; 否则就表示所有进程都执行完毕了。
最后可以通过访问每一个进程的plist[i]->wait_time来得到平均等待时间并打印出来
附录
源代码
//Process Scheduling (Simulation)
/*
author:黎伟杰
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std;
#define NAME_LENGTH 255
#define PROCESS_NUM 5
struct Process
{
char name[NAME_LENGTH];//进程名字
int priority;//优先度
int cost;//进程执行需要时间开销
int used;//已用时间
int wait_time;//等待时间
Process()
{
wait_time = 0;
used = 0;
}
Process(char na[],int ct,int prio)
{
strcpy(name,na);
cost = ct;
priority = prio;
wait_time = 0;
used = 0;
}
Process(Process &rhs)
{
strcpy(name,rhs.name);
cost = rhs.cost;
priority = rhs.priority;
wait_time = rhs.wait_time;
used = rhs.used;
}
void init(char na[],int ct,int prio)
{
strcpy(name,na);
cost = ct;
priority = prio;
wait_time = 0;
used = 0;
}
void print()
{
printf("Process Name:%s \tPriority Value:%d \tWaiting time:%d\n",name,priority,wait_time);
}
};
void sort_priority(Process* plist[],int psize)
{
int i = psize-1;
Process *tmp;
while(i>=0)
{
for (int j=0;j<i;j++)
{
if (plist[i]->priority<plist[j]->priority)
{
tmp = plist[i];
plist[i] = plist[j];
plist[j] = tmp;
}
}
i--;
}
}
//First Come,First Served 先来先服务 ,即FIFO,First In,First Out
void FCFS(Process* plist[],int psize)
{
printf("First Come First Served running...\n");
queue< Process * > fcfs_list;
while(!fcfs_list.empty())fcfs_list.pop();
for (int i=0;i<psize;i++)
{
fcfs_list.push(plist[i]);
}
int time =0;
while(!fcfs_list.empty())
{
Process * excu = fcfs_list.front();
fcfs_list.pop();
excu->wait_time = time;
time += excu->cost;
printf("%s excute %d time units...\n",excu->name,excu->cost);
}
printf("First Come First Served ending...\n");
time = 0;
for (int i=0;i<psize;i++)
{
plist[i]->print();
time += plist[i]->wait_time;
}
double mwt = (double)time/psize;
printf("Mean Waiting Time is %.2lf\n",mwt);
printf("------------------------\n");
}
//Priority Scheduling优先数调度法,非抢占式
void PS(Process* plist[],int psize)
{
printf("Priority Scheduling running...\n");
//因为优先度调度需要根据优先度对进程进行排序后放进队列,为了不影响原顺序,用一个新的数组来暂存排序结果
Process* sort_list[PROCESS_NUM];
for (int i=0;i<psize;i++)
{
sort_list[i] = plist[i];
}
sort_priority(sort_list,psize);
queue< Process * > ps_list;
while(!ps_list.empty())
ps_list.pop();
for (int i=0;i<psize;i++)
{
ps_list.push(sort_list[i]);
}
int time =0;
while(!ps_list.empty())
{
Process * excu = ps_list.front();
ps_list.pop();
excu->wait_time = time;
time += excu->cost;
printf("%s excute %d time units...\n",excu->name,excu->cost);
}
printf("Priority Scheduling ending...\n");
time = 0;
for (int i=0;i<psize;i++)
{
plist[i]->print();
time += plist[i]->wait_time;
}
double mwt = (double)time/psize;
printf("Mean Waiting Time is %.2lf\n",mwt);
printf("------------------------\n");
}
//多级队列,用链表实现
struct MultiQueue
{
queue<Process *> plist;//该级的队列
int quantum_time;//该级别的时间片
int lever;//记录级别
MultiQueue *next;//下一级队列
MultiQueue()
{
lever = 0;
next = NULL;
quantum_time = 0;
while(!plist.empty())
plist.pop();
}
};
//Multilevel feedback queue多级反馈队列调度
void MFQ(Process* plist[],int psize)
{
printf("Multilevel feedback queue running...\n");
MultiQueue *mq = new MultiQueue();
MultiQueue *current;
mq->quantum_time = 1;
mq->lever = 1;
for (int i=0;i<psize;i++)
{
plist[i]->used = 0;
mq->plist.push(plist[i]);
}
int time = 0;
current = mq;
//只有没有下一级队列并且当前队列为空时,才退出
while(! (current->plist.empty() && current->next==NULL))
{
if (current->plist.empty())
current = current->next;
else
{
Process * excu = current->plist.front();
current->plist.pop();
int todo_time = excu->cost - excu->used;
if (todo_time > current->quantum_time )
{
todo_time = current->quantum_time;
excu->used += todo_time;
if (current->next==NULL)
{
current->next = new MultiQueue();
current->next->quantum_time = current->quantum_time+1;
current->next->lever = current->lever+1;
}
current->next->plist.push(excu);
}else
{
excu->wait_time = time - excu->used;
excu->used += todo_time;
}
time += todo_time;
printf("%s excute %d time units at %d layer...\n",excu->name,todo_time,current->lever);
}
}
printf("Multilevel feedback queue ending...\n");
time = 0;
for (int i=0;i<psize;i++)
{
plist[i]->print();
time += plist[i]->wait_time;
}
double mwt = (double)time/psize;
printf("Mean Waiting Time is %.2lf\n",mwt);
printf("------------------------\n");
}
int main()
{
Process *process_list[PROCESS_NUM];
process_list[0]=new Process("P1",10,3);
process_list[1]=new Process("P2",1,1);
process_list[2]=new Process("P3",2,3);
process_list[3]=new Process("P4",1,4);
process_list[4]=new Process("P5",5,2);
FCFS(process_list,5);
PS(process_list,5);
MFQ(process_list,5);
return 0;
}