南邮操作与系统实验思路与实现

本文深入探讨了操作系统中的页面置换算法,包括最佳(OPT)、FIFO、LRU和LFU算法,以及银行家算法在避免死锁中的应用。同时,介绍了进程调度的基本概念和常见算法,如FIFO、高响应比优先(HRRN)、优先级调度和时间片轮转(RR),分析了它们的工作原理和优缺点。
摘要由CSDN通过智能技术生成

页面置换算法

概念补充
  1. 页面调入过程:每当程序要访问的页面不在内存中,便向CPU发出一缺页中断,中断处理程序首先保留CPU环境分析中断原因后转入缺页中断处理程序。先通过查找该页在外存的物理块后,如果此时内存能容纳新页,则将所缺页调入内存,然后修改页表。如果内存已满,则按照某种置换算法,从内存中选出一页准备换出。
  2. 缺页率:在进程访问过程中,访问页面成功(即所访问页面在内存中)的次数为S,访问页面失败(即所访问页面不在内存中,需从外存调入)的次数为F,则总访问次数为A=S+F,缺页率为f=F/A。
  3. “抖动”:刚换出的页很快又要被访问,而现在被调出的页面也是如此,像这样频繁缺页而更换页面,让进程大部分时间都花在页面的换进/换出,从而导致让处理机的利用率急剧下降并趋于0,这个状况称之为”抖动“。
最佳(Optimal,OPT)置换算法

原理:其所选择的被淘汰页是最长时间不被访问的。由于无法预知未来进程情况,所以无法实现。缺页率最低。

实现:前提是静态定义进程访问情况。为每个物理块分配一个计数器,计算当前块下次被访问所隔时间(当永无访问时为为最大),比较三个计算器,将最大的那个物理块所属页面调出。

先进先出(first-in first-out,FIFO)置换算法

原理:总是淘汰最先进入内存的页面,或理解为选择在内存中驻留时间最久的页面淘汰。该算法与实际进程运行的规律不相适应,因为在进程中,有些页面经常被访问,而该算法不能保证这些页面不被淘汰(页面调入的先后不能反映页面的使用情况)。

实现:设置一个替换指针,它总是指向最老的页面。

最近最久未使用(Least Recently Used,LRU)置换算法

原理:选择最近最久未使用的页面淘汰。由于无法预测页面将来的使用情况,只能利用“最近的过去”作为“最近的将来”的相似,然而这两者之间并无必然联系。

实现:为内存中的页面设置一个访问字段t,记录自上次被访问以来经历的时间。当需要淘汰一个页面时,选择现有页面t最大的,并将其他t增加。

最少使用(Least Frequently Used,LFU)置换算法

原理:选择最近最少使用的页面淘汰。局限性与上面方法一样。

实现:为内存中的页面设置一个访问字段n,记录被访问的次数。当需要淘汰一个页面时,选择现有页面n最小的,并将其他n增加。

银行家算法

概念补充
  1. ”死锁“:指各并发过程彼此等待对方使用的资源,且这些并发过程在得到对方资源之前不会释放自己获得的资源。或者说,如果一组进程中的每一个进程都在等待由该组进程中的其他进程才能引发的事件,那么该组进程是死锁的(Deadlock)。
  2. 安全状态:*当系统处于安全状态,可避免发生死锁,反之则可能进入到死锁状态。*在系统进行资源分配前,先计算资源分配的安全性,如果不会进入不安全状态,才会将资源分配给进程,否则让资源等待。在安全状态,系统按某种某种推进顺序为每个进程分配资源,直至满足每个进程对资源的最大需求,使每个进程都可以顺利完成。
算法流程:
  1. 每个新进程在进入系统时,需声明需要的每种资源的最大单元数目(数目不应超过系统拥有的资源总量)。
  2. 当进程请求资源时,先判断当前是否有足够的资源分配给该进程。
  3. 若有,计算资源分配(试探)是否会使系统处于不安全状态。如果不会,才将资源分配给它,否则让进程等待。
参考源码
#include<iostream>
using namespace std;
#define n 5//进程数

typedef struct Vect {//Vector,默认系统资源为三类xyz
	int x;
	int y;
	int z;
	Vect() {
		x = y = z = -1;
	}
	Vect(int a, int b, int c) {
		x = a;
		y = b;
		z = c;
	}

	Vect& operator=(Vect& temp) {
		x = temp.x;
		y = temp.y;
		z = temp.z;
		return *this;
	}

	Vect& operator+(Vect& temp) {
		Vect result;
		result.x = this->x + temp.x;
		result.y = this->y + temp.y;
		result.z = this->z + temp.z;
		return *this;
	}

	Vect& operator-(Vect &temp) {
		Vect result;
		result.x = this->x - temp.x;
		result.y = this->y - temp.y;
		result.y = this->z - temp.z;
		return *this;
	}

	bool operator<(Vect& temp) {
		if (x < temp.x && y < temp.y && z < temp.z)
			return true;
		else return false;
	}

	bool operator<=(Vect& temp) {
		if (x <= temp.x && y <= temp.y && z <= temp.z)
			return true;
		else return false;
	}
}vect;

vect Available ;//每一类可利用资源数目 
vect Max[n];//n进程需要m类资源数 
vect Allocation[n];//n进程当前已分得m类资源数 
vect Need[n];//n进程还需要m类资源数 

int ReadyORWait[n];//0->ready,1->wait
void ChangeStatus();//waitProcess change to readyProcess 
void RequestPut();//controller submmit the request
bool SafetyInspection();//check if there are a solution

int Init()
{
	int i;
	vect Maxres;
	cout << "input the max number of every resource:" << endl;
	cin >> Maxres.x >> Maxres.y >> Maxres.z;
	Available = Maxres;
	for (i = 0; i < n; i++) {
		ReadyORWait[n] = 0;
		cout << "intput Process" << i << "'s *max* need of Resource" << endl;
		cin >> Max[i].x >> Max[i].y >> Max[i].z;
		cout << "intput the Process" << i << "'s*allocation* of Resource" << endl;
		cin >> Allocation[i].x >> Allocation[i].y >> Allocation[i].z;
		if (Maxres < Max[i] || Maxres < Allocation[i]) {
			cout << "ERROR:out of the available!";
			exit(-1);
		}
		Need[i] = Max[i] - Allocation[i];
		Available = Available - Allocation[i];
	}
}


void ChangeStatus() {//change wait to ready 
	for (int i = 0; i < n; i++) {
		if (ReadyORWait[i] == 1)
			ReadyORWait[i]--;
	}
}

void copy(vect* x, vect* temp) {//执行资源分配前备份系统资源状况
	for (int i = 0; i < n; i++)
	{
		temp[i] = x[i];
	}
}

void RequestPut()//主流程
{
	int i;
	vect Request;
	cout << "input which Process you want toallocate" << endl;
	cin >> i;
	cout << "intput which Resource you want to allocate to Process" << endl;
	cin >> Request.x >> Request.y >> Request.z;
	vect AvailableCopy ;
	vect AllocationCopy[n], NeedCopy[n];
	if (Need[i] < Request) {//流程1
		cout << "ERROR:out of the max need!";
	}
	else if (Request <= Available && ReadyORWait[i] == 0) {//流程2
		AvailableCopy = Available;
		copy(Allocation, AllocationCopy);
		copy(Need, NeedCopy);
		Available = Available - Request;//流程3
		Allocation[i] = Allocation[i] + Request;
		Need[i] = Need[i] - Request;
		if (SafetyInspection() == false) {//不安全则作废,返回原来的系统状态
			Available = AvailableCopy;
			copy(AllocationCopy, Allocation);
			copy(NeedCopy, Need);
			ReadyORWait[i]++;//change ready to wait 
		}
	}
	ChangeStatus();
	cout << "success";
}

bool SafetyInspection()//安全性检查:相当与是找到一个解
{
	vect Work ;
	bool Finish[n];
	int Safe = 0;
	Work = Available;
	for (int i = 0; i < n; i++) {
		Finish[i] = false;
	}
	for (int i = 0; i < n; i++) {//每次都分配最大资源
 			while (Finish[i] == false && Need[i] <= Work) {
				Work = Work + Allocation[i];
				Finish[i] = true;
			}
	}
	for (int i = 0; i < n; i++) {
		if (Finish[i] == true)
			Safe++;
	}
	if (Safe == n) return true;
	else {
		cout << "ERROR:UNSAFE"<<endl;
		return false;
	}
}

int main() {
	Init();
	if (SafetyInspection() == false) {
		Init();
	}
 	else cout << "SAFE"<<endl;
    RequestPut();
}

进程调度算法

概念补充
  1. 非抢占方式:一旦把处理机分配给进程就一直让它运行下去,直至该进程完成或被事件阻塞。实现简单,系统开销小。不能用于分时系统和大多数实时系统。
  2. 抢占方式:根据某种原则,去暂停某个执行的进程,将该进程的处理机重新分配给另一进程。现代OS广泛使用,可以防止一个长进程长时间占用处理机。
先进先出FIFO/先来先服务FCFS调度算法

方法:从就绪队列中选择一个最先进入队列的进程,分配处理机,使之投入运行。属于非抢占式。

高响应比优先(HRRN)调度算法

方法:响应比=作业周转时间/作业处理时间=(作业处理时间+作业等待时间)/作业处理时间=1+(作业等待时间/作业处理时间)。先执行的是第一个提交作业,然后其余的作业再用响应比来判断执行顺序。属于非抢占式。是介于FCFS(先来先服务算法)与SJF(短作业优先算法)之间的折中算法。

优先级调度算法(抢占式)

允许优先级高的新到进程抢占当前进程的处理机。

又分静态优先级和动态优先级:

  1. 静态优先级:在创建时确定的,在进程运行期间不变

    短作业优先(short job first,SJF)调度算法

    方法:以作业长短来计算优先级,作业越短,优先级越高。

  2. 动态优先级:在创建之初先赋予一个优先级,然后随进程推进或等待时间的增加而增加。

时间片轮转(RR)进程调度算法

原理:系统根据FCFS策略,将所有就绪进程排成一个就绪队列,每次中断(每过一个时间片),激活进程调度程序,将CPU分配给队首进程。当该进程时间片耗尽或运行完毕时,系统再次将CPU分配给新的队首进程。如果选择很小的时间片,将有利于短作业,但会频繁执行调度进程和进程上下文的切换,增加系统开销,反之,若每个进程都能在一个时间片内完成,RR算法退化为FCFS算法。

注意进程切换的两种情况:

  1. 时间片尚未用完,进程已经完成,则立即激活调度程序,并启动一个新的时间片。
  2. 一个时间片用完,激活调度程序,进程尚未运行完毕,将它送往就绪队列的队尾。

绪队列,每次中断(每过一个时间片),激活进程调度程序,将CPU分配给队首进程。当该进程时间片耗尽或运行完毕时,系统再次将CPU分配给新的队首进程。如果选择很小的时间片,将有利于短作业,但会频繁执行调度进程和进程上下文的切换,增加系统开销,反之,若每个进程都能在一个时间片内完成,RR算法退化为FCFS算法。

注意进程切换的两种情况:

  1. 时间片尚未用完,进程已经完成,则立即激活调度程序,并启动一个新的时间片。
  2. 一个时间片用完,激活调度程序,进程尚未运行完毕,将它送往就绪队列的队尾。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

岚-岚岚岚岚岚

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值