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

  之前学习操作系统的时候对操作系统的一些调度算法比较感兴趣,所以自己模拟实现了一下操作系统算法的调度,我主要模拟实现了短作业优先和先来先服务调度算法。代码有点长,加上测试代码估计有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,增加程序的健壮性。



  • 5
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我可以为您演示一下磁盘调度算法的Python实现。磁盘调度算法操作系统中的一种重要的调度算法,它用于决定磁盘访问请求的顺序,以提高磁盘的读写效率。 在Python中,我们可以使用列表来模拟磁盘请求队列,并使用不同的算法来对其进行调度。下面我将演示三种常见的磁盘调度算法:FCFS、SSTF和SCAN。 首先,我们先定义一个磁盘请求队列: ```python requests = [98, 183, 37, 122, 14, 124, 65, 67] ``` 这个队列中包含了 8 个请求,它们的磁道号分别为 98、183、37、122、14、124、65 和 67。 接下来,我们分别来实现 FCFS、SSTF 和 SCAN 算法的Python代码。 ### 1. FCFS算法 FCFS(First-Come, First-Served)算法是最简单的磁盘调度算法,它按照磁盘请求的先后顺序进行调度。具体实现如下: ```python def fcfs(requests, head): total = 0 for r in requests: total += abs(head - r) head = r return total ``` 在这个函数中,我们首先定义了一个变量 `total`,用于存储磁盘移动的距离总和。然后,我们遍历整个请求队列,计算出每个请求与当前磁头位置之间的距离,将其累加到 `total` 中,并将磁头位置更新为当前请求的位置。最后返回 `total` 即可。 ### 2. SSTF算法 SSTF(Shortest Seek Time First)算法是一种比较常用的磁盘调度算法,它每次选择与当前磁头位置最近的请求进行调度。具体实现如下: ```python def sstf(requests, head): total = 0 while requests: shortest = min(requests, key=lambda x: abs(x - head)) total += abs(head - shortest) head = shortest requests.remove(shortest) return total ``` 在这个函数中,我们首先定义了一个变量 `total`,用于存储磁盘移动的距离总和。然后,我们进入一个循环,每次找出与当前磁头位置最近的请求,并将其从队列中移除。然后,将磁头位置更新为当前请求的位置,并将磁头移动距离累加到 `total` 中。直到队列为空为止,最后返回 `total`。 ### 3. SCAN算法 SCAN(Elevator)算法是一种比较实用的磁盘调度算法,它按照一个方向移动磁头,直到到达磁盘的边界,然后改变方向继续移动。具体实现如下: ```python def scan(requests, head): total = 0 direction = 1 while requests: if head in requests: requests.remove(head) total += 1 head += direction if head == 199: direction = -1 elif head == 0: direction = 1 return total ``` 在这个函数中,我们首先定义了一个变量 `total`,用于存储磁盘移动的距离总和。然后,我们定义了一个变量 `direction`,表示磁头移动的方向,初始值为 1,表示向右移动。 接着,我们进入一个循环,每次判断磁头当前位置是否有请求,如果有,则将其从队列中移除,并将 `total` 加 1。然后,将磁头位置更新为下一个位置,并根据是否到达磁盘边界来改变磁头移动的方向。直到队列为空为止,最后返回 `total`。 好的,以上就是三种常见的磁盘调度算法的Python实现。希望对您有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值