处理机调度算法

一、先来先服务

#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
    评论
### 回答1: 模拟处理机调度算法C是指将任务队列中的作业根据它们的剩余执行时间进行排序,选择剩余执行时间最短的作业来运行,从而达到最短处理时间的目的。 算法C的具体实现步骤如下: 1. 将所有的作业按照顺序加入任务队列。 2. 对于每个时间片,从任务队列中选择剩余执行时间最短的作业。 3. 运行该作业一个时间片,并更新该作业的剩余执行时间。 4. 如果该作业的剩余执行时间为0,则将该作业从任务队列中移除。 5. 重复步骤2-4,直到所有作业都被处理完。 算法C的优点是能够获得最短的处理时间,因为它总是选择剩余执行时间最短的作业来运行。这可以保证作业的响应时间和完成时间都能够得到最小化的保证。 然而,算法C也存在一些缺点。首先,它只考虑了作业的剩余执行时间,而没有考虑作业的优先级、紧迫程度等其他因素。其次,在某些情况下,算法C可能会导致某些作业长时间等待,从而降低了系统的整体效率。 综上所述,算法C是一种以最短处理时间为目标的调度算法。它虽然能够获得较短的响应时间和完成时间,但在某些情况下可能会存在效率问题。因此,在实际应用中,我们需要根据具体的场景和需求选择适合的调度算法。 ### 回答2: 模拟处理机调度算法C是一种常用的调度算法,主要针对多道程序设计环境下的处理机分配问题。该算法根据进程的优先级和执行时间确定处理机的调度顺序。 具体而言,模拟处理机调度算法C的步骤如下: 1. 首先,根据进程的优先级来对进程队列进行排序,优先级高的进程排在前面。 2. 然后,根据排好序的进程队列,按照进程的优先级高低依次分配处理机。即,优先级高的进程先执行。 3. 在进程执行的过程中,根据进程的执行时间进行时间片轮转。当一个进程执行的时间达到了时间片的限制时,将处理机分配给下一个优先级最高的进程。 4. 如果有多个进程具有相同的优先级,可以采用轮流调度的方式,即每个进程轮流分配处理机,每个进程执行同样的时间片。 5. 当所有进程都执行完毕时,结束调度算法。 模拟处理机调度算法C的特点是能够保证高优先级的进程优先执行,从而可以更好地满足多道程序设计环境下的实时性要求。此外,该算法还可以避免某些低优先级进程长时间占用处理机资源,从而提高整个系统的效率。 然而,模拟处理机调度算法C也存在一些不足之处。由于优先级高的进程可能长时间占用处理机资源,可能导致其他低优先级进程的运行较慢甚至出现饥饿现象。另外,该算法没有考虑进程的响应时间,可能导致一些高优先级的进程等待时间过长。 综上所述,模拟处理机调度算法C是一种常用的调度算法,适用于多道程序设计环境。它通过优先级和执行时间的综合考虑来分配处理机资源,可以满足实时性要求,但需要注意饥饿和响应时间的问题。 ### 回答3: 模拟处理机调度算法C是一种优先级调度算法,即根据作业的优先级来确定任务的执行顺序。该算法的核心思想是通过比较作业的优先级,选择优先级最高的作业先执行,以提高处理机的利用率和系统的响应速度。 算法C的步骤如下: 1. 初始化调度队列,将所有作业按照优先级从高到低依次加入队列。 2. 从队列中选择优先级最高的作业,将其分配给处理机执行。 3. 处理机执行该作业一段时间后,检查是否有更高优先级的作业进入队列。 - 如果有,将当前作业暂停,将新作业加入队列并分配给处理机执行。 - 如果没有,继续执行当前作业,直到该作业完成或出现更高优先级的作业。 4. 重复步骤2和步骤3,直到所有作业完成。 模拟处理机调度算法C的优点是能够根据作业的优先级进行灵活调度,确保高优先级作业的及时执行,从而提高系统的性能和响应速度。然而,这种算法可能存在优先级反转的问题,即一个低优先级的长作业会阻塞高优先级的短作业,从而降低系统的效率。 为了解决优先级反转的问题,可以引入抢占式优先级调度算法,如模拟处理机调度算法P。该算法在作业进入队列时会进行实时的优先级比较,如果出现更高优先级的作业,则立即将当前作业暂停,将新作业分配给处理机执行,以保证高优先级作业的及时处理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值