计算机操作系统-进程管理和死锁避免
1.题目要求描述
1、本次课程设计通过编写和调试一个仿真模拟银行家算法避免死锁的程序,观察产生死锁的,条件,并采用银行家算法,有效地避免死锁的发生。
2、了解多道程序系统中,多个进程并发的动态资源分配。在多道程序系统中,由于在内存中驻留了多道程序,他们共享资源,并发执行,动态的申请资源。
3、掌握产生死锁的原因、产生死锁的必要的条件和处理死锁的基本方法。
4、掌握死锁的方法,系统安全的基本概念。
5、掌握最具有代表性的避免死锁的算法——银行家算法,了解资源在进程并发执行过程中的资源分配策略。
6、提高运用操作系统知识解决实际问题的能力,锻炼实际的编程能力,提高调查研究的能力,提高查阅技术文献、资料以及编写软件设计文档的能力。
本次课程设计的内容是采用银行家算法,编写和调试一个仿真模拟银行家算法避免死锁的程序。设计n个并发进程共享3类不同的系统资源,即1类资源、2类资源、3类资源。进程可以动态的申请资源,系统按各个进程的申请动态的分配资源。可以添加进程,进程动态的申请资源,系统进行安全性检查,判断是否可以为申请资源的进程分配资源。如果能够找到安全序列,则系统为进程分配资源,否则原先的试探分配资源作废。
2.程序流程图及源代码注释
进程管理源代码功能流程图
程序设计功能流程图
(1)模块间调用关系图:
(2)进程申请资源的流程图:
(3)系统进行安全性检查的流程图:
3.程序设计
本系统设计两个窗体,主窗体用来添加进程,副窗体用来检查资源分配后系统是否出于安全状态。
1、主窗体含有三个板块,一个添加进程板块,一个用来显示目前系统内资源分配情况的板块,一个进程申请资源的板块。
(1)添加进程板块:需在一个textbox中给出进程名,而且进程名必须是唯一的,使用三个combobox让用户选择进程执行所需要系统为之分配的最大资源数目,一个button按钮,用来提交用户进行的操作,如果用户没有给出进程名,那么进程名默认为进程+系统内总进程数目减一。
(2)显示板块:使用listview控件以表格形式显示,当用户提交新添加的进程后,在显示板块会显示出此进程的进程名、所需各种资源的最大数目、系统已分配的资源数目、此进程还需的各种资源数目,而且将系统目前可利用各种资源数目显示出来。
(3)申请资源板块:使用一个combobox让用户选择需要申请资源的进程名,在控件combobox中只含有用户已经输入的进程名,用户只需选择。使用三个combobox让用户选择进程申请各种资源的数目,一个button按钮,用来提交是哪个进程申请了什么资源及其数目。
2、副窗体含有两个板块,一个是显示系统试探着把资源分配给进程的后板块,一个是利用安全算法显示安全的资源分配情况板块。
(1)显示资源分配后的板块:系统试探着将资源分配给申请资源的进程,并将分配后的结果使用listview控件以表格形式显示到窗体上,并将系统剩余资源显示到窗体上。listview控件上还应该显示是哪个进程申请的资源。
(2)显示安全的资源分配情况板块:一个button按钮,用来检查系统是否处于安全状态,若处于安全状态,则在listview控件中列出对资源分配情况的分析,并在只读的textbox中输出安全序列。
3、本系统附带一个例子,假定在系统中有5个进程{p0,p1,p2,p3,p4},在t0时刻的资源分配情况如图所示:
使用一个button按钮,命名为课本实例。点击此按钮后,进程数组被初始化为{p0,p1,p2,p3,p4},各个进程的信息如上图所示,然后进程进行资源申请。
4、模块设计:本系统含有三个模块,即添加进程模块、申请资源模块、检查安全性模块。这三个模块全部都使用到类Progress,其定义如下:
public class Progress
{
private string name; //进程名,是唯一的,任两个进程不能重名
public int[] Max = new int[3]; //进程最大可申请的各种资源
//数目
public int[] Allocation = new int[3];//系统已分配给进程的各种资源
//的数目
public int[] Need = new int[3]; //进程还需要的各种资源的数目
public int[] Request = new int[3]; //存放进程提出申请各种资源的//数目
}
(1)添加进程模块
本模块包括一个textbox,3个combobox,一个button,在textbox中输入进程名,在combobox中选择进程所需要申请的最大资源数,点击button按钮进程提交用户的操作。
本模块所用到的数据类型有:
Progress progress = new Progress(); //创建新进程
Progress[] allProgress = new Progress[50]; //存放添加的所有进程
progressNumber = 0; //进程数目,每添加一个新进程都加1
(2)申请资源模块
本模块进程动态的申请资源,包括4个combobox,一个button。在第一个combobox中选择申请资源的进程名,在此combobox中的进程名都是用户已添加的进程名。另外三个combobox选择进程申请的各种资源的数目。点击button按钮提交用户所做的操作。
本模块所用的数据类型有:
Progress[] allProgress = new Progress[50];//系统已含有的所有进程
int[] Available = new int[3] { 10, 5, 7 }; //资源数组
int temp; //提出申请的资源号
Progress pro = new Progress(); //创建新进程
BankForm bankfrm = new BankForm(this); //创建新的副窗体
(3)检查安全性模块
本模块是系统进行安全性检查模块,检查在此时刻系统是否处于安全状态,如果能够找到一个安全序列,说明系统出于安全状态,否则处于不安全状态。本模块包括一个listview控件,用来显示找到安全序列后,系统安全分配资源的情况;一个textbox,用来显示安全序列;一个button按钮,点击button按钮系统进行安全性检查,检查后的结果会显示在listview和textbox中。
本模块所用到的数据类型有:
bool message = false;//作为找到安全序列的标志,值为true则找到安全序列
static Progress[] allProgress=new Progress[ 50];//系统中目前所有的进程
static int progressNumber; //系统目前的进程数
static int[] Available = new int[3]; //存放系统目前可利用资源数目
int temp; //目前申请资源的进程号
SafeXuLie[] safexulie; //存放安全序列
int[] progressQueue = new int[BankForm.progressNumber]; //存放安全序列//的进程号
int t=0;
int k = 0; // progressQueue的号
int[] work = new int[3]; //系统释放一定的资源后可利用资源数目
BankForm.Available.CopyTo(work, 0); //置Work[i]=Available[i]
int[] Finish = new int[BankForm.progressNumber];
int[] need = new int[3];
int[] allocation = new int[3];
safexulie = new SafeXuLie[BankForm.progressNumber];
public class SafeXuLie //填充副窗体的ListView控件时使用
{
public int[] work;
public int[] need;
public int[] allocation;
public int[] workAllocation;
public SafeXuLie(); //构造方法
}
5、数据结构说明:
本次课程设计中使用了类Progress,类SafeXuLie,类MainForm,类BankForm,它们的定义及在程序中的作用如下:
(1)类Progress
在程序中创建进程,保存进程的全部信息,包括进程名、进程可申请的最大资源数目、系统已分配给进程的资源数目、进程执行还需要申请的资源、进程申请资源数目。其具体定义如下:
public class Progress
{
private string name; //进程名,是唯一的,任两个进程不能重名
public int[] Max = new int[3]; //进程最大可申请的各种资源的数目
public int[] Allocation = new int[3];//系统已分配给进程的各种资源//的数目
public int[] Need = new int[3]; //进程还需要的各种资源的数目
public int[] Request = new int[3]; //存放进程提出申请各种资源的//数目
public string Name //进程名的属性
{
get { return name; } //获得进程名
set { name = value; } //设置进程名
}
public Progress (){}; //不含参数的构造方法,用来创建进程
// 含3个参数构造方法,name是进程名
// m是最大可申请的各种资源的数目数组
// a是系统已分配给进程的各种资源的数目数组
// n是进程还需要的各种资源的数目数组
public Progress (string name,int[] m,int[] a,int[] n);
}
(2)类SafeXuLie
类SafeXuLie在程序中用于保存进程的部分信息,包括:工作向量work,表示系统可提供给进程继续运行所需的各种资源数目,在执行安全序列算法时置为系统目前可利用资源数目;需求向量need,某一进程还需申请的资源数目;分配向量allocation,表示系统中每一类资源当前已分配给某一进程的资源数系统;workAllocation,系统分配资源后,假定进程执行完毕后释放的资源加上系统中原有的可利用资源数目。其具体定义如下:
public class SafeXuLie //填充副窗体的ListView控件时使用
{
public int[] work; // 系统可提供给进程继续运行所需的各种资源数目
public int[] need; // 某一进程还需申请的资源数目
public int[] allocation; //系统已分配给某一进程的资源数系统
public int[] workAllocation; //进程执行完毕后,系统可利用资源数目
public SafeXuLie() //构造方法
{
work = new int[3];
need = new int[3];
allocation = new int[3];
workAllocation = new int[3];
}
}
(3)类MainForm
创建主窗体,初始化主窗体,给主窗体添加程序中所用到的控件,点击窗体上的控件触发事件。其具体定义如下:
public partial class MainForm : Form
{
private Progress progress = new Progress(); //创建进程progress
public Progress[] allProgress = new Progress[50];//存放添加的所有
//进程
private int progressNumber = 0; //进程数目
public int[] Available = new int[3] { 10, 5, 7 }; //资源数组
private int temp; //提出申请的资源号
public MainForm(); //初始化主窗体
private void button1_Click(object sender, EventArgs e);//关闭主窗//体
//进程申请资源,点击主窗体上的申请资源板块的确定按钮触发此事件
private void ApplyResourcebutton_Click(object sender, EventArgs e);
//添加新进程,点击主窗体上的添加新进程板块的确定按钮触发此事件
private void AddProgressButton_Click_1(object sender, EventArgs e);
//判断进程名是否唯一,若唯一则返回true,否则返回false
public bool nameUnique();
// 填充ListView控件
public void fillListView(ListView listView1, int[] a);
// 填充ListView控件,此控件中首列是进程名
public void fillListView(Progress progress1, ListView listView1, int[] a);
// 更新ListView控件的第temp个项目
public void updateListView(int temp, ListView listView, int[] a);
// 更新ListView控件的第0个项目,用来更新窗体上显示的系统可利用资源数目
public void updateListView(ListView listView, int[] a);
//初始化主窗体上的控件的值
private void MainForm_Load(object sender, EventArgs e);
// 检查进程申请的资源数目是否小于其需求数目,若小于则返回true
public bool checkApplyResNeed(Progress p)
// 检查进程申请的资源数目是否小于可利用资源数目,若小于则返回true
public bool checkApplyResAvail(Progress p)
// 将进程数组a中的数据复制到进程数组b中
public void copyto(Progress[] a, Progress[] b)
// 课本上的实例,给进程数组设置一个实例
private void Examplebutton_Click(object sender, EventArgs e)
}
(4)类BankForm
创建副窗体,初始化副窗体,给副窗体添加程序中所用到的控件,点击窗体上的控件触发事件。其具体定义如下:
public partial class BankForm : Form
{
private bool message = false; //作为找到安全序列的标志
private Progress progress = new Progress(); //创建进程对象
//主窗体的进程数组副本
public static Progress[] allProgress=new Progress[ 50]; //所有进程
public static int progressNumber; //进程数
public static int[] Available = new int[3]; //系统可利用资源数目
public int temp; //申请资源的进程号
public MainForm mainfrm; //声明主窗体对象,用来往主窗体传值
private SafeXuLie[] safexulie; //存放安全序列,进程名组成
public BankForm(); //初始化副窗体,不含参数构造方法
public BankForm(MainForm maf); //初始化副窗体,参数是主窗体对象
//给副窗体上的控件置初值
private void BankForm_Load(object sender, EventArgs e);
//点击窗体上返回按钮,关闭副窗体并向主窗体传值
private void button1_Click(object sender, EventArgs e);
//点击窗体上检查安全性按钮
private void SafeButton_Click(object sender, EventArgs e);
public bool safeSequence(int[] progressQueue); //安全算法
public bool Compare(int [] a,int [] b); // 比较两个数组的大小
public void fill(int[] a) // 填充listViewWork控件,a是安全序列
}
6、系统测试
(1)输入如下测试数据:
点击添加按钮,结果如下图所示,由于没有输入进程名,系统默认进程名分别为进程A,进程B,进程C。
(2)然后进程A发出请求向量{3,2,2},进入父窗体,在第一个表格中,带有阴影的一行是目前申请资源的进程名。点击检查安全性按钮,结果如图所示,能够找到安全序列,并将安全序列输出,显示系统对资源分配情况的分析:
点击返回按钮,回到主界面,由于可以找到一个安全序列,说明系统处于安全状态,可以把资源分配给进程A,分配结果如图所示,进程A的allocation、need已经改变,系统可利用资源数目available也已经发生改变,由原来的{10,5,7}变为{7,3,5}:
(3)进程B发出请求向量{5,2,3},由于发出的请求向量大于进程1最大可申请资源数目,系统提示申请资源错误,如下图所示:
(4)将进程B发出的请求向量改为{3,2,3},进入副窗体。点击检查安全性按钮,系统找到安全序列。点击返回按钮,回到主窗体。结果如图所示:
(5)进程C发出请求向量{3,1,2},点击确定按钮,进入副窗体。点击检查安全性按钮,由于系统剩余的可利用资源数目{1,0,0}已经不能满足任何进程的需求,故系统提示安全性错误,如下图所示:
点击返回按钮,结果如图所示,系统不给进程B分配资源,表格中的数据不发生变化,如下图所示:
点击链接查看文档代码