1、优先权调度算法
在模拟优先权调度算法实验中,实现了 非抢占式静态优先权进程调度算法 和 非抢占式动态优先权进程调度算法。如下:
(1)非抢占式静态优先权进程调度算法
#include <iostream>
#include <list>
#include <iomanip>
using namespace std;
//进程PCB
typedef struct {
int id; //进程id
int priority; //优先权(优先数越大优先权越小)
int allTime; //运行所需总时长
int finishTime; //结束时间
} PCB;
//PCB初始化数组
static PCB originData[5] = {
{1,3,4,-1},{2,1,3,-1},{3,4,2,-1},{4,2,1,-1},{5,5,3,-1}
};
list<PCB> readyList; //声明就绪队列(泛型链表)
int systemTime = 0; //系统时间
//初始化泛型链表
void initList(){
for(int i=0;i<5;i++){
readyList.push_back(originData[i]);
}
}
//获取先权最大的进程PCB
list<PCB>::iterator getHighestPriority(){
list<PCB>::iterator highit = readyList.begin(); //迭代器指针highit用于指向优先权最大的进程PCB
for(list<PCB>::iterator it = highit; it!=readyList.end(); it++ ){ //迭代器指针it指向readyList第一个元素,向下遍历
if((*it).priority > (*highit).priority){
highit = it;
}
}
return highit;
}
int main(){
initList(); //初始化readyList泛型链表
cout<<setw(11)<<"id"<<" "<<"priority"<<" "<<"allTime"<<" "<<"finishTime"<<endl;
while(!readyList.empty()){
list<PCB>::iterator high = getHighestPriority();
systemTime += (*high).allTime;
(*high).finishTime = systemTime;
cout<<setw(11)<<(*high).id<<setw(11)<<(*high).priority<<setw(11)<<(*high).allTime<<setw(11)<<(*high).finishTime<<endl;
readyList.erase(high);
}
return 0;
}
执行结果:
(2)非抢占式动态优先权进程调度算法
/* ***非抢占式动态优先权进程调度算法*** */
#include <iostream>
#include <list>
#include <iomanip>
using namespace std;
//进程PCB
typedef struct {
int id; //进程id
int priority; //优先权
int allTime; //运行所需总时长
int remainTime; //剩余运行时长
int finishTime; //结束时间
} PCB;
//PCB初始化数组
static PCB originData[5] = {
{1,20,4,4,-1},{2,25,3,3,-1},{3,15,5,5,-1},{4,23,1,1,-1},{5,18,2,2,-1}
};
list<PCB> readyList; //声明就绪队列(泛型链表)
int systemTime = 0; //系统时间
int timeSlice = 2; //时间片
//初始化泛型链表
void initList(){
for(int i=0;i<5;i++){
readyList.push_back(originData[i]);
}
}
//获取先权最大的进程PCB
list<PCB>::iterator getHighestPriority(){
list<PCB>::iterator highit = readyList.begin(); //迭代器指针highit用于指向优先权最大的进程PCB
for(list<PCB>::iterator it = highit; it!=readyList.end(); it++ ){ //迭代器指针it指向readyList第一个元素,向下遍历
if((*it).priority < (*highit).priority){
highit = it;
}
}
return highit;
}
int main(){
initList(); //初始化readyList泛型链表
cout<<setw(11)<<"id"<<" "<<"priority"<<" "<<"allTime"<<" "<<"remainTime"<<" "<<"finishTime"<<endl;
while(!readyList.empty()){
list<PCB>::iterator it = getHighestPriority();
if( ((*it).remainTime > timeSlice) ){ //比较进程剩余运行时长与时间片的大小
systemTime += timeSlice;
(*it).remainTime -= timeSlice;
(*it).priority += 3; //执行进程优先数+3
readyList.push_back(*it); //环境数据加入readyList尾部
}
else if((*it).remainTime == timeSlice) {
systemTime += timeSlice;
(*it).remainTime -= timeSlice;
(*it).finishTime = systemTime;
}
else{
systemTime += (*it).remainTime;
(*it).remainTime = 0;
(*it).finishTime = systemTime;
}
cout<<setw(11)<<(*it).id<<setw(11)<<(*it).priority<<setw(11)<<(*it).allTime<<setw(11)<<(*it).remainTime<<setw(11)<<(*it).finishTime<<endl;
for(list<PCB>::iterator iter = readyList.begin(); iter!=readyList.end(); iter++ ){ //迭代器指针it指向readyList第一个元素,向下遍历
if( (*it).id != (*iter).id ){
(*iter).priority --; //等待进程优先数-1
}
}
readyList.erase(it); //删除it指向的泛型元素
}
return 0;
}
执行结果:
2、时间片轮转调度算法
/* ***时间片轮转调度算法*** */
#include <iostream>
#include <list>
#include <iomanip>
using namespace std;
//进程PCB
typedef struct {
int id; //进程id
int arriveTime; //到达时间
int allTime; //运行所需总时长
int remainTime; //剩余运行时长
int finishTime; //结束时间
} PCB;
//PCB初始化数组
static PCB originData[5] = {
{1,10,2,2,-1},{2,5,3,3,-1},{3,0,2,2,-1},{4,8,4,4,-1},{5,0,5,5,-1}
};
list<PCB> readyList; //声明就绪队列(泛型链表)
int systemTime = 0; //系统时间
int timeSlice = 2; //时间片
//按到达时间排序
void sorkArriveTime (){
PCB temp;
for (int i=0; i<5; i++){
for (int j=i+1; j<5; j++){
if ( originData[i].arriveTime > originData[j].arriveTime ){
temp = originData[i];
originData[i] = originData[j];
originData[j] = temp;
}
}
}
}
//readyList初始化
void initList(){
sorkArriveTime (); //按到达时间排序
for(int i=0; i<5; i++){
readyList.push_back(originData[i]); //向readyList尾部加入数据
}
}
//主函数
int main() {
initList(); //初始化readyList泛型链表
cout<<setw(11)<<"id"<<" "<<"arriveTime"<<" "<<"allTime"<<" "<<"remainTime"<<" "<<"finishTime"<<endl;
while(!readyList.empty()){ //readyList不为空执行循环
list<PCB>::iterator it = readyList.begin();
if( ((*it).remainTime > timeSlice) ){ //比较进程剩余运行时长与时间片的大小
systemTime += timeSlice;
(*it).remainTime -= timeSlice;
readyList.push_back(*it); //环境数据加入readyList尾部
}
else if((*it).remainTime == timeSlice) {
systemTime += timeSlice;
(*it).remainTime -= timeSlice;
(*it).finishTime = systemTime;
}
else{
systemTime += (*it).remainTime;
(*it).remainTime = 0;
(*it).finishTime = systemTime;
}
cout<<setw(11)<<(*it).id<<setw(11)<<(*it).arriveTime<<setw(11)<<(*it).allTime<<setw(11)<<(*it).remainTime<<setw(11)<<(*it).finishTime<<endl;
readyList.erase(it); //删除it指向的泛型元素
}
return 0;
}
执行结果:
int timeSlice = 2; //时间片为2
调试分析
(1)优先权调度算法
在非抢占式静态优先权进程调度算法中,处理机从就绪队列选取优先级最大的进程执行,直到该进程执行结束或阻塞,再从就绪队列中选择下一个进程。在忽略进程阻塞的情况下,也可忽略时间片以及PCB环境的保护。
在非抢占式静态优先级进程调度算法中,设置优先数越大,优先级越小的方案。执行进程每执行完一个时间片优先权减小(优先数+3),就绪队列中的等待程序每等待一个时间片优先权增大(优先数-1),并设置时间片timeSlice =2。
(2)时间片轮转调度算法
时间片轮转调度中,进程本就是以到达时间排列整齐的。在解决进程的初始排序问题时,先用了冒泡排序,为了代码效率换用sort()函数实现list链表的排序,而在VC6.0中并不支持list::sort(),只能还是选择了最简单的冒泡排序方法,并且对于时间片轮转的机制来看,对于进程的排序按进程到达时间依次加入就绪队列。
由于存在进程在结束时的时间片内执行不足一个完整的时间片的情况,并且由于进程PCB的成员都设置为int型,若设置时间片为1,则并不能实现进程执行不完整时间片的情况,因此设置的时间片应大于1。
由于时间片运转的机制,进程每次执行一个时间片其PCB都会改变,需要每次进行当前环境PCB的记录,而当进程剩余执行时间大于或等于或小于时间片时,系统对这三种情况的处理又有所不同,因此必须用if语句判断以执行不同的代码。
重点扩展:
(1)linux中每个进程都有一个优先数,进程能否占用处理器的优先权取决于进程的优先数,优先数越小则优先权越高。
(2)sort( )函数:vector的迭代器是随机访问迭代器,支持泛型算法的sort及其排序算法。,而list容器上的迭代器是双向的,不支持随机访问,因此不能使用需要随机访问迭代器的sort算法。C++为list容器提供了特有的算法,但不能支持VC6.0版本。
总结
经过此次模拟进程调度实验,深入理解了进程的优先权调度方式和时间片轮转调度方式,优先权调度方式利用进程优先数大小实现调度顺序,时间片轮转方式借助进程到达时间的顺序以时间片的大小分段执行。在时间片轮转中,要注意进程当前环境PCB的保护,以便进程之后的继续执行。动态优先级调度算法中,优先级的动态变化是基于时间片改变的,注意需要设置时间片。