处理机调度算法

一、先来先服务

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <new>
#include <string>
#include <cstdio>
using namespace std;

unsigned int sysTime = 0;			// 模拟系统的时钟,每运行一次就加1

enum Status {Ready, Complete};		// 就绪态Ready,完成态Complete

class PCB
{
public:	// 权限待改进
	string name;
	Status condition;				// 进程当前的状态
	unsigned int arriveTime;		// 到达时间
	unsigned int serveTime;			// 服务时间,每执行一次减1,是变化的
	unsigned int serveTimeConst;	// serveTime运行一次减1,因为最后要算带权周转时间,故用serveTimeConst来保存初始的serveTime
	unsigned int startTime;			// 开始执行时间
	unsigned int endTime;			// 完成时间
	unsigned int T;					// 周转时间turnaroundTime
	double W;						// 带权周转时间weightedTurnaroundTime
	PCB *next;

	// 构造函数
	PCB(string _name = "", unsigned int _arriveTime = 0, unsigned int _serveTime = 0)
		:name(_name),
		condition(Ready),
		arriveTime(_arriveTime),
		serveTime(_serveTime),
		serveTimeConst(_serveTime),
		startTime(0),
		endTime(0),
		T(0),
		W(0),
		next(NULL){}
};

class ReadyQueue
{
public:
	PCB *head;						// 头指针指向头结点
	PCB *tail;						// 指向尾结点

	// 构造函数
	ReadyQueue()
	{
		head = new(nothrow) PCB();	// 带头结点的链队列
		if (NULL == head)
		{
			cout << "StackOverflow!" << endl;
			exit(-1);
		}

		tail = head;				// 设尾指针,初始化为头指针
	}

	// 输入所有进程
	void Input()
	{
		cout << "请输入各进程名、到达时间及估计服务时间:" << endl;
		string name;
		unsigned int arrT;
		unsigned int serT;
		while (cin >> name >> arrT >> serT)
		{
			EnQueue(name, arrT, serT);	// 在就绪队列Q中插入刚来的进程
		}
	}

	// PCB入队,用进程的到达时间和服务时间来初始化
	void EnQueue(string _name, unsigned int _arriveTime, unsigned int _serveTime)
	{
		PCB *p = new(nothrow) PCB(_name, _arriveTime, _serveTime);
		if (NULL == p)
		{
			cout << "StackOverflow!" << endl;
			exit(-1);
		}

		tail->next = p;
		tail = tail->next;		
	}

	// 判空
	bool IsEmpty()
	{
		return head == tail;
	}

	// 执行队首进程
	void Run()
	{
		if (IsEmpty())
		{
			cout << "队列为空,不能执行!" << endl;
			exit(-1);
		}
		cout << "就绪队列:";	// 不空则先输出所有就绪进程
		for (PCB *q = head->next; q != NULL; q = q->next)
		{
			cout << q->name;
			if (q != this->tail)
			{
				cout << "->";
			}			
		}

		PCB *p = head->next;				// 取出将要执行的进程
		while (sysTime < p->arriveTime)		// 若此时进程“还未到达”,则等待(这个最好在入队时判断,但入队和出队应并发执行,待改进)
		{
			++sysTime;
		}
		p->startTime = sysTime;
		cout << "\n进程" << p->name << "开始运行,估计服务时间为" << p->serveTime << ",此时系统时间为:" << sysTime << endl;
		cout << "已运行时间\t剩余运行时间" << endl;
		while (p->serveTime != 0)		// 执行
		{
			++sysTime;
			--(p->serveTime);			// 模拟服务时间-1操作

			cout << sysTime - p->startTime << "\t\t"
				<< p->serveTime << endl;
		}
		// 退出执行时服务时间为0,而serveTimeConst保存了初始的服务时间,以便算带权周转时间
		cout << "进程" << p->name << "执行完毕!" << endl << endl;

		p->condition = Complete;
		p->endTime = sysTime;
		p->T = p->endTime - p->arriveTime;
		p->W = (double)(p->T) / p->serveTimeConst;	// 注意类型转换
	}

	// 删除队首进程,返回该进程的地址
	PCB* DeQueue()
	{
		if (IsEmpty())			// 判空
		{
			cout << "队空,不得删除!" << endl;
			exit(-1);
			//return NULL;
		}

		PCB *p = head->next;
		head->next = p->next;
		if (tail == p)			// 最后一个进程出队时要特别注意
		{
			tail = head;
		}

		return p;
		//不释放结点,因为最后要输出所有结点的信息
	}

	// 析构函数
	~ReadyQueue()					// 后面的结点由StorePCB释放
	{
		delete head;
		head = NULL;
	}
};

class StorePCB
{
public:
	PCB *front;
	PCB *rear;

	// 构造函数
	StorePCB()
	{
		front = new(nothrow) PCB();	// 带头结点的链队列
		if (NULL == front)
		{
			cout << "StackOverflow!" << endl;
			exit (-1);
		}

		rear = front;				// 设尾指针,初始化为头指针
	}

	// 输出所有进程信息
	void Output()
	{
		cout << "各进程信息:\n进程名\t周转时间\t带权周转时间" << endl;
		for (PCB *p = front->next; p != NULL; p = p->next)
		{
			cout << p->name << "\t"
				<< p->T << "\t\t"
				<< p->W << endl;
		}
	}

	// 把p指向的PCB插入S
	void EnQueue(PCB *p)
	{
		if (p == NULL)
		{
			cout << "不能向存储队列中插入空!" << endl;
			exit (-1);
		}

		p->next = NULL;				// 重要,以便最后释放
		rear->next = p;
		rear = rear->next;
	}

	// 析构函数
	~StorePCB()
	{
		PCB *p = NULL;
		PCB *q = NULL;
		for (p = front; p != NULL; p = q)
		{
			q = p->next;
			delete p;
			p = NULL;
		}
		front = NULL;
		rear = NULL;
	}
};

int main(int argc, char **argv)
{
	//freopen("cin.txt", "r", stdin);
	//freopen("cout.txt", "w", stdout);

	ReadyQueue Q;						// 就绪队列Q
	StorePCB S;							// S用于存储执行完毕的进程(修改指针即可)
	unsigned int count = 1;

	// 输入进程
	Q.Input();

	// 执行进程
	while (!Q.IsEmpty())				// 只要就绪队列不为空就一直执行
	{
		cout << "*********************************** Case " << count++ << " ***********************************" << endl;
		Q.Run();						// 执行就绪队首进程
		PCB *tmp = Q.DeQueue();			// 得到刚执行完毕的进程的地址
		S.EnQueue(tmp);					// 将执行完毕的进程存储在S中
	}
	cout << "***************************** 进程全部执行完毕! *****************************" << endl << endl;

	// 输出进程的执行信息(周转时间和带权周转时间)
	S.Output();

	return 0;
}

二、抢占式动态优先权

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <new>
#include <queue>
#include <string>
#include <cstdio>
using namespace std;

unsigned int sysTime = 0;			// 模拟系统的时钟,每运行一次就加1

enum Status {Ready, Complete};		// 就绪态Ready,完成态Complete

class PCB
{
public:	// 权限待改进
	unsigned int priorityNum;		// 优先数(优先数越大,优先权越低,0表示最高优先权)
	string name;					// 进程名
	Status condition;				// 当前的状态
	unsigned int arriveTime;		// 到达时间
	unsigned int serveTime;			// 服务时间(每执行一次减1,是变化的)
	unsigned int serveTimeConst;	// serveTime运行一次减1,因为最后要算带权周转时间,故用serveTimeConst来保存初始的serveTime
	unsigned int startTime;			// 开始执行时间
	unsigned int endTime;			// 完成时间
	unsigned int T;					// 周转时间turnaroundTime
	double W;						// 带权周转时间weightedTurnaroundTime
	PCB *next;						// 指向下个PCB

	// 构造函数
	PCB(string _name = "",
		unsigned int _arriveTime = 0,
		unsigned int _serveTime = 0,
		unsigned int _priorityNum = 0
		)
		:name(_name),
		condition(Ready),
		arriveTime(_arriveTime),
		serveTime(_serveTime),
		serveTimeConst(_serveTime),
		startTime(0),
		endTime(0),
		T(0),
		W(0),
		next(NULL),
		priorityNum(_priorityNum){}

	// 比较优先级,优先数
	bool operator<(const PCB &obj) const
	{
		return this->priorityNum > obj.priorityNum;	// 规定优先级与优先数相反
	}
};

// 执行队首进程一次
void Run(priority_queue<PCB> &Q)
{
	if (Q.empty())
	{
		cout << "队列为空,不能执行!" << endl;
		exit(-1);
	}

	cout << "就绪队列:";
	priority_queue<PCB> myQ(Q);		// 要输出优先队列,只能每次都输出队首,故创建一个副本
	while (!myQ.empty())
	{
		cout << myQ.top().name;
		myQ.pop();
		if (!myQ.empty())
		{
			cout << " -> ";
		}
	}
	cout << endl;

	PCB head(Q.top());	// 优先队列不能对其队首直接修改?
	Q.pop();
	//head.startTime = sysTime;	// 开始执行时间无意义?
	sysTime++;
	head.priorityNum++;
	head.serveTime--;
	if (head.serveTime == 0)	// 运行完毕
	{
		cout << "进程" << head.name << "执行完毕" << endl;
		head.condition = Complete;
		head.endTime = sysTime;
		head.T = head.endTime - head.arriveTime;
		head.W = (double)(head.T) / head.serveTimeConst;
	}
	else
	{
		Q.push(head);
	}
}

int main(int argc, char **argv)
{
	freopen("cin.txt", "r", stdin);

	priority_queue<PCB> Q;	// ReadyQueue
	string name;
	unsigned int arrT;
	unsigned int serT;
	unsigned int priorityNum;

	// 输入进程
	cout << "请输入各进程名、到达时间及估计服务时间:" << endl;
	while (cin >> name >> arrT >> serT >> priorityNum)
	{
		Q.push(PCB(name, arrT, serT, priorityNum));	// 在就绪队列Q中插入刚来的进程
	}
	cout << endl;

	while (!Q.empty())
	{
		Run(Q);	// 运行一次
	}


	return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值