操作系统复习——处理机调度和死锁
1. 在多道程序环境下,进程数目往往多于处理机数目,致使它们竞争使用处理机。这就要求系统能按某种算法,动态地把处理机分配给就绪队列中的一个进程,使之执行。一个作业从提交开始,往往要经历三级调度:高级调度、中级调度、低级调度。
1.高级调度:调度对象是作业。
2.中级调度:提高内存利用率和系统吞吐量。
3.低级调度:它所调度的对象是进程。进程调度是最基本的一种调度。进程调度方式有两种调度方式:非抢占方式和抢占方式(基于优先权,短作业优先,时间片原则)。
2. 作业调度和进程调度的区别:
(1)作业调度为进程活动做准备,进程调度使进程活动起来
(2)作业调度次数少,进程调度次数多
(3)有的系统不设作业调度,但进程调度必不可少
3. 调度算法:
1.FCFS先来先服务:该算法既可用于作业调度,也可用于进程调度。当在作业调度中采用该算法时,每次调度都是从后备作业队列中选择一个或多个最先进入该队列的作业,将它们调入内存,为它们分配资源、创建进程,然后放入就绪队列。在进程调度中采用FCFS算法时,则每次调度是从就绪队列中选择一个最先进入该队列的进程,为之分配处理机,使之投入运行。该进程一直运行到完成或发生某事件而阻塞后才放弃处理机。FCFS 算法比较有利于长作业(进程),而不利于短作业(进程)。
2.短作业优先:
3.高优先权优先调度算法(动态优先权):
4.基于时间片的轮转调度算法:在分时系统中,为保证能及时响应用户的请求,必须采用基于时间片的轮转式进程调度算法。每次调度时,把CPU 分配给队首进程,并令其执行一个时间片。时间片的大小从几ms 到几百ms。当执行的时间片用完时,由一个计时器发出时钟中断请求,调度程序便据此信号来停止该进程的执行,并将它送往就绪队列的末尾;然后,再把处理机分配给就绪队列中新的队首进程,同时也让它执行一个时间片。这样就可以保证就绪队列中的所有进程在一给定的时间内均能获得一时间片的处理机执行时间。
4. 死锁:
1.产生死锁的原因:竞争资源(多个进程竞争共享的资源),进程间推进顺序非法(进程请求和释放的资源顺序不当)
2.产生死锁的必要条件:互斥条件,请求和保持条件,不剥夺条件,环路等待条件。
3.处理死锁的几种方式:预防死锁,避免死锁,检测死锁,解除死锁。
4.预防死锁的方法:利用银行家算法
5.银行家算法是一种最有代表性的避免死锁的算法。在避免死锁方法中允许进程动态地申请资源,但系统在进行资源分配之前,应先计算此次分配资源的安全性,若分配不会导致系统进入不安全状态,则分配,否则等待。为实现银行家算法,系统必须设置若干数据结构。
安全序列是指一个进程序列{P1,…,Pn}是安全的,即对于每一个进程Pi(1≤i≤n),它以后尚需要的资源量不超过系统当前剩余资源量与所有进程Pj (j < i )当前占有资源量之和。(即在分配过程中,不会出现某一进程后续需要的资源量比其他所有进程及当前剩余资源量总和还大的情况)
注:存在安全序列则系统是安全的,如果不存在则系统不安全,但不安全状态不一定引起死锁。
原理过程:
系统给当前进程分配资源时,先检查是否安全:在满足当前的进程X资源申请后,是否还能有足够的资源去满足下一个距最大资源需求最近的进程(如某进程最大需要5个单位资源,已拥有1个,还尚需4个),若可以满足,则继续检查下一个距最大资源需求最近的进程,若均能满足所有进程,则表示为安全,可以允许给当前进程X分配其所需的资源申请,否则让该进程X进入等待。
(注:检查过程中,每拟满足一个进程,则进行下个检查时,当前可用资源为回收上一个进程资源的总值,每满足一个进程表示此进程已结束,资源可回收。)
算法过程:
1).银行家算法中的数据结构
(1).可利用资源向量
(2).最大需求矩阵
(3).分配矩阵
(4).需求矩阵
2).对于当前需要申请资源的进程Pi
(1) 检查if( Request[ i ][ j ]<=Need[ i ][ j ] ) goto (2)
else error(“进程 i 对资源的申请量大于其说明的最大值 ”);
(2)检查 if ( Request[ i ][ j ]<=Available[ j ] ) goto (3)
else wait() ; /*注意是等待!即在对后续进程的需求资源判断中,若出现不符合的则安全检查结束,当前进程进入等待*/
(3) 系统试探地把资源分给Pi 并修改各项属性值 (具体是否成立,则根据安全检查的结果)
Available[ j ] =Available[ j ] — Request[ i ][ j ]
Allocation[ i ][ j ]=Allocation[ i ][ j ] +Request[ i ][ j ]
Need[ i ][ j ]=Need[ i ][ j ]— Request[ i ][ j ]
代码实现:
#include <iostream>
#include <string.h>
#include <string>
using namespace std;
const int maxnsource = 100;
const int maxnprocess = 50;
int available[maxnsource];//可以使用的资源。
int max[maxnprocess][maxnprocess];//最大需求矩阵。
int allocation[maxnprocess][maxnprocess];//已经分配的矩阵。
int need[maxnprocess][maxnprocess];//还需要的矩阵。
int requestsource[maxnprocess][maxnprocess];//进程请求的矩阵。
int finish[maxnprocess];//进程是否能得到足够的资源使其结束。
int n, m;
int i, j;
int p[maxnsource];//记录进程号
int safe()//判断是否为安全的
{
int cnt = 0;
int flag = 0;
int temp[maxnsource];
for (i = 0; i < n; i++)
temp[i] = available[i];
for (i = 0; i < m; i++)
{
if (finish[i] == 0)
{
for (j = 0; j < n; j++)
{
if (need[i][j] > temp[j])
break;
}
if (j == n)
{
finish[i] = 1;
for (int k = 0; k < n; k++)
temp[k] += allocation[i][k];
p[cnt++] = i;
i = -1;//这里不是0,重置之后i++会变为1,就错了。
}
else
continue;
if (cnt == m)
{
cout << "系统是安全的" << endl;
cout << "安全序列:" << endl;
for (i = 0; i<cnt; i++)
{
cout << p[i];
if (i != cnt - 1)
{
cout << "-->";
}
}
cout << "" << endl;
return 1;
}
}
}
cout << "系统是不安全的" << endl;
return 0;
}
void bank()//银行家算法
{
int cur;
while (1)
{
cout << "输入要申请资源的进程号" << endl;
cin >> cur;
cout<< "输入进程所请求的各资源的数量" << endl;
for (int i = 0; i < n; i++)
cin >> requestsource[cur][i];
for (int i = 0; i < n; i++)
{
if (requestsource[cur][i] > need[cur][i])
{
cout << "输入的请求数超过进程的需求量!请重新输入!" << endl;
continue;
}
if (requestsource[cur][i] > available[i])
{
cout << "输入的请求数超过系统有的资源数!请重新输入!" << endl;
continue;
}
}
for (int i = 0; i < n; i++)
{
available[i] -= requestsource[cur][i];
allocation[cur][i] += requestsource[cur][i];
need[cur][i] -= requestsource[cur][i];
}
for (int i = 0; i < m; i++)
finish[i] = 0;
if (safe())
{
cout << "同意分配请求!" << endl;
}
else
{
cout << "您的请求被拒绝!" << endl;
for (int i = 0; i < n; i++)
{
available[i] += requestsource[cur][i];
allocation[cur][i] -= requestsource[cur][i];
need[cur][i] += requestsource[cur][i];
}
for (int i = 0; i < m; i++)
finish[i] = 0;
string s;
cout << "是否还想再次请求分配吗?如果想,请输入YES" << endl;
cin >> s;
if (s == "YES")
continue;
else
break;
}
}
}
int main()
{
memset(finish, 0, sizeof(finish));
cout << "输入进程的数量:";
cin >> m;
cout << "输入资源的种类:";
cin >> n;
cout << "输入每个进程最多所需要的资源数:";
for (i = 0; i < m; i++)
for (int j = 0; j < n; j++)
cin >> max[i][j];
cout << "输入每个进程已经分配的资源数:";
for (i = 0; i < m; i++)
{
for (j = 0; j < n; j++)
{
cin >> allocation[i][j];
need[i][j] = max[i][j] - allocation[i][j];
if (need[i][j] < 0)
{
cout << "输入的第" << i + 1 << "个进程所拥有的第" << j + 1 << "个资源数 错误,请重新输入:" << endl;
j--;
continue;
}
}
}
cout << "输入各资源现有的资源数:";
for (i = 0; i < n; i++)
cin >> available[i];
/*for (i = 0; i < m; i++)
{
for (int j = 0; j < n; j++)
cout << max[i][j] << " ";
cout << endl;
}
for (i = 0; i < m; i++)
{
for (int j = 0; j < n; j++)
cout << allocation[i][j] << " ";
cout << endl;
}
for (i = 0; i < m; i++)
{
for (int j = 0; j < n; j++)
cout << need[i][j] << " ";
cout << endl;
}*/
safe();
bank();
return 0;
}