您的位置:首页 > 理论基础 > 数据结构算法

模拟实现操作系统调度算法

2016-04-06 22:01 597 查看
  之前学习操作系统的时候对操作系统的一些调度算法比较感兴趣,所以自己模拟实现了一下操作系统算法的调度,我主要模拟实现了短作业优先和先来先服务调度算法。代码有点长,加上测试代码估计有300行左右吧,放在这里的话看起来也不方便(算了,还是放在下面吧,免得看的人觉得麻烦)。我先把实现的结果截图放在下面吧,然后再附上代码,其实在我的github上面也有这些代码的,地址: https://github.com/admin-zou/DS/tree/master/scheduling







头文件: //scheduling.h

#ifndef _SCHEDULING_
#define _SCHEDULING_

#include <iostream>
#include <stdlib.h>
using namespace std;

enum Tag{UNSHD,SHD}; //标记是否被调度过

struct PCB
{
int      pcbid;			//进程号
size_t  arrtime;			//到达时间
size_t  sertime;			//服务时间
size_t  begtime;			//开始时间
size_t  endtime;			//完成时间
size_t  turntime;		//周转时间
float    weighttime;		//带权周转时间
PCB *   next;			//指向下个节点的指针
Tag     tag;				//标记是否被调度过

PCB(int n=0,size_t a=0,size_t s=0)
:pcbid(n),arrtime(a),sertime(s),begtime(0),endtime(0)
,turntime(0),weighttime(0),next(NULL),tag(UNSHD)
{}
};

class scheduling
{
public:
scheduling():_curtime(0),_tasknum(0)
{
_head = new PCB();
}

/////先来先服务算法
void FIFS()
{
if(empty())
{
cout<<"没有任务";
exit(-1);
}
_clear();  //清理一下,可重复计算
_sort_t(); //按到达时间排序
PCB* cur = _head->next;
while(NULL != cur)
{
if(_curtime < cur->arrtime)
{
_curtime = cur->arrtime;
}
cur->begtime = _curtime;
cur->endtime = _curtime + cur->sertime;		//完成时间等于开始时间加服务时间
cur->turntime = cur->endtime - cur->arrtime;	 //周转时间=完成时间-到达时间
cur->weighttime  = (float)cur->turntime / (float)cur->sertime;  //带权周转时间=周转时间/服务时间
cur->tag = SHD; //标记为已经服务
_curtime += cur->sertime;
cur = cur->next;
}
}

/////短作业

void Short()
{
if (empty())
{
cout << "没有任务";
exit(-1);
}
_clear();  //清理一下,可重复计算
_sort_t(); //按到达时间排序

PCB* cur = _head->next;
while (NULL != cur)
{
if (_curtime < cur->arrtime)
{
_curtime = cur->arrtime;
}
cur->begtime = _curtime;
cur->endtime = _curtime + cur->sertime;		//完成时间等于开始时间加服务时间
cur->turntime = cur->endtime - cur->arrtime;	 //周转时间=完成时间-到达时间
cur->weighttime = (float)cur->turntime / (float)cur->sertime; //带权周转时间=周转时间/服务时间
cur->tag = SHD; //标记为已经服务
_curtime += cur->sertime;
cur = cur->next;

//将该进程调度完的时刻已经到达的进程按短作业优先排序
_sort_l(cur,_curtime);  //从该进程开始进行短作业排序

}
}

void Init_task()
{
int tasknum=0;
size_t id=0;
size_t atime=0;
size_t stime=0;
cout<<"请输入任务的个数:";
cin>>tasknum;
for(int i = 0; i<tasknum;i++)
{
cout<<"请分别输入任务的编号,到达时间,运行时间:";
cin>>id>>atime>>stime;
push(id,atime,stime);
}
}

void Push()
{
size_t id=0;
size_t atime=0;
size_t stime=0;
cout<<"请分别输入任务的编号,到达时间,运行时间:";
cin>>id>>atime>>stime;
push(id,atime,stime);
}

void Print()
{
if(empty())
return ;
PCB* cur = _head->next;
printf("进程号 到达时间 服务时间 开始时间 完成时间 周转时间 带权周转时间 \n");
while(NULL != cur)
{
printf("%4d %6d %8d %9d %7d  %8d\t %0.2f\n",cur->pcbid, cur->arrtime ,cur->sertime ,cur->begtime, cur->endtime ,cur->turntime ,cur->weighttime);
cur = cur->next;
}
}

protected:
bool empty()
{
return _tasknum == 0;
}

bool push(int n,size_t a,size_t s) //插入到链表尾部
{
PCB * newtask = new PCB(n,a,s);
PCB * cur = _head;
while(NULL != cur->next)
cur =cur->next;
cur->next=newtask;
_tasknum++;
return true;
}

void _clear()
{
if(empty())
return ;
PCB* cur = _head->next;
while(NULL != cur)
{
cur->begtime = 0;
cur->endtime = 0;
cur->turntime = 0;
cur->weighttime = 0;
cur->tag = UNSHD;
cur = cur->next ;
}
_curtime = 0;
}

// 按照到达时间排序
void _sort_t()
{
if(empty() || _tasknum == 1)
return;
PCB* prev = _head->next;
PCB* cur = prev->next;
for(int i = 0; i< _tasknum-1; i++)
{
for(int j = 0; j<_tasknum-i-1; j++)
{
if (prev->arrtime > cur->arrtime)
{
_Swap(prev, cur);
}
prev = cur;
cur = cur->next;
}
prev=_head->next;
cur = prev->next;
}
}

// 按照作业长短排序
void _sort_l(PCB*& head,size_t curtime)
{
if (NULL == head || NULL == head->next)
return;
PCB* prev = head;
PCB* cur = prev->next;
int size = 0;  //计算进程的数目
PCB* tmp = head;
while (tmp)
{
++size;
tmp = tmp->next;
}

for (int i = 0; cur->arrtime < curtime && i < size - 1; i++)
{
if (prev->arrtime > curtime)
{//作业还没到达就不排序
return;
}
for (int j = 0; j < size - i - 1; j++)
{
if (cur && cur->arrtime <= curtime)
{
int ptime = prev->sertime;
int ctime = cur->sertime;
if (ptime > ctime)
{
_Swap(prev, cur);
}
}
prev = cur;
cur = cur->next;
}
prev = head;
cur = prev->next;
}
}

void _Swap(PCB * prev,PCB * cur)
{
swap(prev->arrtime,cur->arrtime);
swap(prev->pcbid ,cur->pcbid );
swap(prev->sertime ,cur->sertime );
}

private:
PCB *	_head;
size_t  _curtime;
size_t  _tasknum;	//作业个数
};

#endif


测试文件:

#define	_CRT_NOWANRINGS
#include"scheduling.h"

int main()
{
int select=1;
scheduling mytask;
while(select)
{
cout<<"****************************"<<endl;
cout<<"*   1.初始化               *"<<endl;
cout<<"*   2.新插入一个进程       *"<<endl;
cout<<"*   3.先来先服务调度算法   *"<<endl;
cout<<"*   4.短作业调度算法       *"<<endl;
cout<<"*   5.显示调度情况         *"<<endl;
cout<<"*   0.退出                 *"<<endl;
cout<<"****************************"<<endl;
int item=0;
cout<<"请输入:";
cin>>select;
switch(select)
{
case 1:
mytask.Init_task();
break;
case 2:
mytask.Push();
break;
case 3:
mytask.FIFS();
break;
case 4:
mytask.Short();
break;
case 5:
mytask.Print();
cout << endl;
break;
default:
break;
}
}
return 0;
}

//测试条件
/*
5
1 0 4
2 2 4
3 3 3
4 5 6
5 6 3
*/

   总结:

       1.上面的程序基于是我对操作系统调度算法的理解所写出来的,主要模拟了先来先服务和短作业优先调度两种调度算法,其中涉及到了c++,数据结构以及操作系统和算法等方面的只是,实现它确实大有所益。

       2.在上面的小项目中我是通过计算出各种调度算法的周转时间,带权周转时间等等来评价调度算法的效率的,能够在一定范围内评估调度算法的性能,以及某些场景适合于使用哪种调度算法。

      3.我是通过单链表来组织相关的作业的调度需要的数据的,这样确实有好处,也有缺陷,这和链表的优缺点相对应。不过在数据量较小的时候还是很不错的。

    其中主要的难点在于很难分析出所有可能出现的情况,以及各种情况下的行为。还有就是,需要对操作系统的调度算法有一定的理解,否则就容易出现于实际不符的结果,比如说短作业优先调度,怎样理解这种调度方式呢,我举个例子吧:一开始时只有一个作业在调度,但是其所需时间比较长,在他执行过程中来了其他作业,但是作业时间很短,先调度这个短作业可能会更优,那么我们需要怎么处理呢,这就涉及到了是否允许抢占资源的问题(当然在我的实现中是不可抢占资源的)。最后说明一下在开发的时候一定要多调试,减少bug,增加程序的健壮性。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息