计算机操作系统实验报告
题 目 利用银行家算法避免死锁
一、 实验目的:
1、 加深了解有关资源申请、避免死锁等概念,并体会和了解死锁和避免死 锁的具体实施方法。
2、 要求编写和调试一个系统动态分配资源的简单模拟程序,观察死锁产生 的条件,并采用银行家算法,有效的防止和避免死锁的发生。
二、 实验内容:
用银行家算法实现资源分配:
设计五个进程{p0,p1,p2,p3,p4}共享三类资源{A,B,C}的系统,例如, {A,B,C}的资源数量分别为10,5,7。进程可动态地申请资源和释放资源, 系统按进程的申请动态地分配资源, 要求程序具有显示和打印各进程的某一 个时刻的资源分配表和安全序列; 显示和打印各进程依次要求申请的资源号
以及为某进程分配资源后的有关资源数据。
三、 问题分析与设计:
1、 算法思路:
先对用户提出的请求进行合法性检查,即检查请求是否大于需要的,是 否大于可利用的。若请求合法,则进行预分配,对分配后的状态调用安全性 算法进行检查。若安全,则分配;若不安全,则拒绝申请,恢复到原来的状 态,拒绝申请。
2、 银行家算法步骤:
如果Request v or二Need,则转向步骤 ⑵;否则,认为出错,因 为它所需要的资源数已超过它所宣布的最大值。
如果Requestv or二Available,则转向步骤(3);否则,表示系统中 尚无足够的资源,进程必须等待。
系统试探把要求的资源分配给进程 Pi, 并修改下面数据结构中的数 值:
Available=Available-Request[i];
Allocation=Allocation+Request;
Need=Need-Request;
系统执行安全性算法,检查此次资源分配后,系统是否处于安全状 态。
3、安全性算法步骤:
( 1 )设置两个向量
工作向量Work。它表示系统可提供进程继续运行所需要的各类资源数 目,执行安全算法开始时, Work=Allocation;
布尔向量 Finish 。它表示系统是否有足够的资源分配给进程, 使之运 行完成,开始时先做 Finish[i]=false ,当有足够资源分配给进程时,令 Finish[i]=true 。
(2)从进程集合中找到一个能满足下述条件的进程:
Fi nish[i]=false
Needvor二Work
如找到,执行步骤( 3);否则,执行步骤( 4)。
( 3)当进程 P 获得资源后,可顺利执行,直至完成,并释放出分配给它的资源,故应执行:
Work=Work+Allocation;
Finish[i]=true;
转向步骤( 2)。
否则,系( 4)如果所有进程的 Finish[i]=true, 则表示系统处于安全状态; 统处于不安全状态。
否则,系
4、流程图:
系统主要过程流程图
银行家算法流程图
安全性算法流程图
5、主要数据结构
假设有M个进程N类资源,则有如下数据结构:
int max[M*N] M 个进程对N类资源的最大需求量
int available[N] 系统可用资源数
int allocated[M*N] M 个进程已经得到N类资源的资源量
int need[M*N] M 个进程还需要N类资源的资源量
int worked[] 系统提供给进程继续运行所需的各类资源数目
四、 源代码
import .*;
import .*;
import .*;
public class OsBanker extends JFrame { etBounds(0, 0 + pi * 20, 60,
20);
labelProcessLabel2[pi].setBounds(0, 0 + pi * 20, 60, 20);
}
(75, 120, 60, 120);
(75, 270, 60, 120);
for (int pi = 0; pi < 6; pi++) {
(labelProcessLabel1[pi], null);
(labelProcessLabel2[pi], null);
}
(pPanel1);
(pPanel2);
(pPanel4);
for (int si = 0; si < 5; si++)
for (int pi = 0; pi < 6; pi++) {
textNeed[pi][si] = new JTextField();
textNeed[pi][si]
.setBounds(150 + si * 50, 120 + pi * 20, 50, 20); textNeed[pi][si].setEditable(false);
textAllocation[pi][si] = new JTextField(); textAllocation[pi][si].setBounds(150 + si * 50, 270 +
pi * 20,
50, 20);
}
}
textAllocation[pi][si].setEditable(false);
for (int si = 0; si < 5; si++) {
textAvailable[si] = new JTextField();
textAvailable[si].setEditable(false);
textAvailable[si].setBounds(150 + si * 50, 70, 50, 20); textRequest[si] = new JTextField();
textRequest[si].setEditable(false);
textRequest[si].setBounds(150 + si * 50, 430, 50, 20); (textAvailable[si], null);
(textRequest[si], null);
}
for (int pi = 0; pi < 6; pi++)
for (int si = 0; si < 5; si++) {
(textNeed[pi][si], null);
(textAllocation[pi][si], null);
}
(80, 430, 50, 20);
(textProcessName, null);
(550, 500);
(false);
(" 银行家算法 (SXJ)");
(null);
(EXIT_ON_CLOSE); dd(scrollPane);
(450, 400);
(false);
(EXIT_ON_CLOSE);
(false);
(false);
(false);
(false);
(new ActionListener() {
public void actionPerformed(ActionEvent e) { etEditable(true);
textAllocation[i][j].setEditable(true); textAvailable[j].setEditable(true);
}
}
}
});
(new ActionListener() {
public void actionPerformed(ActionEvent e) { Init();
(true);
});
(new ActionListener() {
public void actionPerformed(ActionEvent e) { count = 0;
SafeSequence = new int[processNum]; worked = new int[resourceNum];
Finish = new boolean[processNum]; copyVector(worked, available); Safety(0);
(" 安全序列数量: " + count);
if (flag) {
(" 当前系统状态:安全 ");
(true);
(true);
(true);
for (int i = 0; i < resourceNum; i++) { textRequest[i].setEditable(true);
}
} else {
(" 当前系统状态:不安全 ");
}
}
}
}
(false);
}
});
(new ActionListener() {
public void actionPerformed(ActionEvent e) { count = 0;
for (int i = 0; i < processNum; i++) {
Finish[i] = false;
}
("");
flag = false;
RequestResource();
}
});
(new ActionListener() {
public void actionPerformed(ActionEvent e) { /*
* (""); ("");
*/
(false);
("");
for (int i = 0; i < processNum; i++) { for (int j = 0; j < resourceNum; j++) { textNeed[i][j].setText(""); textAllocation[i][j].setText(""); textAvailable[j].setText(""); textRequest[j].setText(""); etEditable(false); etEditable(false); etEditable(false); textRequest[j].setEditable(false); ("");
Finish[i] = false;
}
}
flag = false;
(false); etText());
}
max = new int[processNum][resourceNum]; allocated = new int[processNum][resourceNum]; need = new int[processNum][resourceNum];
for (int i = 0; i < processNum; i++) {
for (int j = 0; j < resourceNum; j++) {
max[i][j] = (textNeed[i][j].getText()); allocated[i][j] = (textAllocation[i][j] .getText());
}
}
for (int i = 0; i < resourceNum; i++)
for (int j = 0; j < processNum; j++)
need[j][i] = max[j][i] - allocated[j][i];
for (int i = 0; i < resourceNum; i++) for (int j = 0; j < processNum; j++) { available[i] -= allocated[j][i];
if (available[i] < 0) {
(" 您输入的数据有误 ,请重新输入 ");
}
}
}
void Safety(int n) etText());
}
if (!Smaller(request, need[processname])) { (" 资源请求不符该进程的需求量 .");
} else if (!Smaller(request, available)) {
("
(" 可用资源不足以满足请求 , 进程需要等待 .");
("
(" 可用资源不足以满足请求 , 进程需要等待 .");
} else {
Sub(available, request);
Add(allocated[processname], request);
Sub(need[processname], request);
copyVector(worked, available);
Safety(0);
if (flag) {
(" 可立即分配给该进程 !");
} else {
(" 分配后导致系统处于不安全状态 !, 不可立即分配 ");
Add(available, request);
Sub(allocated[processname], request);
Add(need[processname], request);
}
}
// }
}
}
五、实验结果:
初始界面: 初始化:
检测安全性:
请求资源:
(1)进程 2( 1,0,2)
(2)进程 5( 3,3,0)
(3)进程 1( 0,2,0)
六、 遇到的问题及不足之处:
1、程序编写的时候规定最大资源数和最大进程数均 <=6。
2、程序直接初始化了 6 个进程框,既浪费了内存空间,又对可视化界 面的美观造成影响。
3、未对输入异常进行处理:比如在请求资源的第一个方框中只能填入 进程的数字编号,当填入的为非整数时,程序会抛出异常。
4、未解决进程名中对字符串的处理,直接固定进程名为数字,用户不 能直接输入原有的进程名,造成不好的用户体验。