死鎖:
死鎖產生的現場:當A進程P S2信號量而B進程P S1信號量時就會產生死鎖,因為S2信號量需要B進程釋放,而S1信號量需要A進程釋放,因此兩個進程都在等相互的資源,造成死鎖。

死鎖產生的條件:
互斥條件:進程要求對所分配的資源進行排它性控制,即在一段時間內某資源僅為一進程所占用。(信號量s1 s2為互斥的信號量,只能被一個進程占用)
請求和保持條件:當進程因請求資源而阻塞時,對已獲得的資源保持不放。(A進程在獲取s2阻塞時,一直占用s1)
不可剝奪條件:進程已獲得的資源在未使用完之前,不能剝奪,只能在使用完時由自己釋放。(s1只能由A進程釋放,s2只能由B進程釋放)
環路等待條件:在發生死鎖時,必然存在一個進程--資源的環形鏈。(A B 進程都是環形鏈路)
避免死鎖的算法:
銀行家算法是避免死鎖的一種重要方法,防止死鎖的機構只能確保上述四個條件之一不出現,則系統就不會發生死鎖。通過這個算法可以用來解決生活中的實際問題,如銀行貸款等。
程序實現思路銀行家算法顧名思義是來源於銀行的借貸業務,一定數量的本金要應多個客戶的借貸周轉,為了防止銀行加資金無法周轉而倒閉,對每一筆貸款,必須 考察其是否能限期歸還。在操作系統中研究資源分配策略時也有類似問題,系統中有限的資源要供多個進程使用,必須保證得到的資源的進程能在有限的時間內歸還 資源,以供其他進程使用資源。如果資源分配不得到就會發生進程循環等待資源,則進程都無法繼續執行下去的死鎖現象。
把一個進程需要和已占有資源的情況記錄在進程控制中,假定進程控制塊PCB其中“狀態”有就緒態、等待態和完成態。當進程在處於等待態時,表示系統不能滿 足該進程當前的資源申請。“資源需求總量”表示進程在整個執行過程中總共要申請的資源量。顯然,,每個進程的資源需求總量不能超過系統擁有的資源總 數, 銀行算法進行資源分配可以避免死鎖.
一.程序流程圖:
1.初始化算法流程圖:

2.銀行家算法流程圖:

3.安全性算法流程圖:

二.銀行家算法設計:
1.設進程i提出請求Request[n],則銀行家算法按如下規則進行判斷。
(1)如果Request[n]>Need[i,n],則報錯返回。
(2)如果Request[n]>Available,則進程i進入等待資源狀態,返回。
(3)假設進程i的申請已獲批准,於是修改系統狀態:
Available=Available-Request
Allocation=Allocation+Request
Need=Need-Request
(4)系統執行安全性檢查,如安全,則分配成立;否則試探險性分配作廢,系統恢復原狀,進程等待。
2.安全性檢查
(1)設置兩個工作向量Work=Available;Finish =False
(2)從進程集合中找到一個滿足下述條件的進程,
Finish =False
Need<=Work
如找到,執行(3);否則,執行(4)
(3)設進程獲得資源,可順利執行,直至完成,從而釋放資源。
Work=Work+Allocation
Finish=True
GO TO 2
(4)如所有的進程Finish =true,則表示安全;否則系統不安全。
3.數據結構
假設有M個進程N類資源,則有如下數據結構:
#define W 10
#define R 20
int A ; //總進程數
int B ; //資源種類
int ALL_RESOURCE[W]; //各種資源的數目總和
int MAX[W] ; //M個進程對N類資源最大資源需求量
int AVAILABLE ; //系統可用資源數
int ALLOCATION[W] ; //M個進程已經得到N類資源的資源量
int NEED[W] ; //M個進程還需要N類資源的資源量
int Request ; //請求資源個數
5.4主要函數說明
void showdata(); //主要用來輸出資源分配情況
void changdata(int); //主要用來輸出資源分配后后的情況
void rstordata(int); //用來恢復資源分配情況,如:銀行家算法時,由於分配不安全則要恢復資源分配情況
int chkerr(int); //銀行家分配算法的安全檢查
void bank() ; //銀行家算法
銀行家算法的課程設計(二)VC++6.02008-01-28 15:29源程序
數據結構分析:
假設有M個進程N類資源,則有如下數據結構:
#define W 10
#define R 20
int A ; //總進程數
int B ; //資源種類
int ALL_RESOURCE[W]; //各種資源的數目總和
int MAX[W] ; //M個進程對N類資源最大資源需求量
int AVAILABLE ; //系統可用資源數
int ALLOCATION[W] ; //M個進程已經得到N類資源的資源量
int NEED[W] ; //M個進程還需要N類資源的資源量
int Request ; //請求資源個數
第3章 程序清單#include <iostream>
using namespace std;
#define MAXPROCESS 50 /*最大進程數*/
#define MAXRESOURCE 100 /*最大資源數*/
int AVAILABLE[MAXRESOURCE]; /*可用資源數組*/
int MAX[MAXPROCESS][MAXRESOURCE]; /*最大需求矩陣*/
int ALLOCATION[MAXPROCESS][MAXRESOURCE]; /*分配矩陣*/
int NEED[MAXPROCESS][MAXRESOURCE]; /*需求矩陣*/
int REQUEST[MAXPROCESS][MAXRESOURCE]; /*進程需要資源數*/
bool FINISH[MAXPROCESS]; /*系統是否有足夠的資源分配*/
int p[MAXPROCESS]; /*記錄序列*/
int m,n; /*m個進程,n個資源*/
void Init();
bool Safe();
void Bank();
int main()
{
Init();
Safe();
Bank();
}
void Init() /*初始化算法*/
{
int i,j;
cout<<"\t---------------------------------------------------"<<endl;
cout<<"\t|| ||"<<endl;
cout<<"\t|| 銀行家算法 ||"<<endl;
cout<<"\t|| ||"<<endl;
cout<<"\t|| 計科04151 李宏 ||"<<endl;
cout<<"\t|| ||"<<endl;
cout<<"\t|| 0415084211 ||"<<endl;
cout<<"\t---------------------------------------------------"<<endl;
cout<<"請輸入進程的數目:";
cin>>m;
cout<<"請輸入資源的種類:";
cin>>n;
cout<<"請輸入每個進程最多所需的各資源數,按照"<<m<<"x"<<n<<"矩陣輸入"<<endl;
for(i=0;i<m;i++)
for(j=0;j<n;j++)
cin>>MAX[j];
cout<<"請輸入每個進程已分配的各資源數,也按照"<<m<<"x"<<n<<"矩陣輸入"<<endl;
for(i=0;i<m;i++)
{
for(j=0;j<n;j++)
{
cin>>ALLOCATION[j];
NEED[j]=MAX[j]-ALLOCATION[j];
if(NEED[j]<0)
{
cout<<"您輸入的第"<<i+1<<"個進程所擁有的第"<<j+1<<"個資源數錯誤,請重新輸入:"<<endl;
j--;
continue;
}
}
}
cout<<"請輸入各個資源現有的數目:"<<endl;
for(i=0;i<n;i++)
{
cin>>AVAILABLE;
}
}
void Bank() /*銀行家算法*/
{
int i,cusneed;
char again;
while(1)
{
cout<<"請輸入要申請資源的進程號(注:第1個進程號為0,依次類推)"<<endl;
cin>>cusneed;
cout<<"請輸入進程所請求的各資源的數量"<<endl;
for(i=0;i<n;i++)
{
cin>>REQUEST[cusneed];
}
for(i=0;i<n;i++)
{
if(REQUEST[cusneed]>NEED[cusneed])
{
cout<<"您輸入的請求數超過進程的需求量!請重新輸入!"<<endl;
continue;
}
if(REQUEST[cusneed]>AVAILABLE)
{
cout<<"您輸入的請求數超過系統有的資源數!請重新輸入!"<<endl;
continue;
}
}
for(i=0;i<n;i++)
{
AVAILABLE-=REQUEST[cusneed];
ALLOCATION[cusneed]+=REQUEST[cusneed];
NEED[cusneed]-=REQUEST[cusneed];
}
if(Safe())
{
cout<<"同意分配請求!"<<endl;
}
else
{
cout<<"您的請求被拒絕!"<<endl;
for(i=0;i<n;i++)
{
AVAILABLE+=REQUEST[cusneed];
ALLOCATION[cusneed]-=REQUEST[cusneed];
NEED[cusneed]+=REQUEST[cusneed];
}
}
for(i=0;i<m;i++)
{
FINISH=false;
}
cout<<"您還想再次請求分配嗎?是請按y/Y,否請按其它鍵"<<endl;
cin>>again;
if(again=='y'||again=='Y')
{
continue;
}
break;
}
}
bool Safe() /*安全性算法*/
{
int i,j,k,l=0;
int Work[MAXRESOURCE]; /*工作數組*/
for(i=0;i<n;i++)
Work=AVAILABLE;
for(i=0;i<m;i++)
{
FINISH=false;
}
for(i=0;i<m;i++)
{
if(FINISH==true)
{
continue;
}
else
{
for(j=0;j<n;j++)
{
if(NEED[j]>Work[j])
{
break;
}
}
if(j==n)
{
FINISH=true;
for(k=0;k<n;k++)
{
Work[k]+=ALLOCATION[k];
}
p[l++]=i;
i=-1;
}
else
{
continue;
}
}
if(l==m)
{
cout<<"系統是安全的"<<endl;
cout<<"安全序列:"<<endl;
for(i=0;i<l;i++)
{
cout<<p;
if(i!=l-1)
{
cout<<"-->";
}
}
cout<<""<<endl;
return true;
}
}
cout<<"系統是不安全的"<<endl;
return false;
}
輸出數據

銀行家算法的模擬實現”是本學期操作系統課程唯一的課程設計。在設計此程序的過程中,我遇到過許多問題,也學到了很多東西。本程序的設計實現主要是用 C++語言實現,通過對程序算法的設計優化、輸出顯示的格式設計、輸入過程中的異常處理等一些設計過程中的問題的考慮解決,在C++學習上也有了很大的進 步。程序設計過程中開始遇到的最大的問題是算法的結構設計問題,課本上只給了設計要求及簡單的算法,要真正實現還需要考慮很多方面。在算法的數據結構設計 上考慮了很長時間。在程序設計中先后參考了很多網絡資料,也參考了一些別人寫的的程序,綜合這些算法思想和自己的思路對程序做了很好的設計方式,對一些算 法的優越性等也作了一些考慮。此外考慮最多的就是異常錯誤處理的設計。一個好的程序必須能在各種環境下都有其相應的處理方式,至少能應對一些常見的可能發 生的錯誤。比如一般的要求輸入為數字時,如果輸入了一個非數字字符,程序就會立即出錯無法繼續運行,本程序針對這個問題設計了一個shuzi();函數進 行處理,處理方式為:接受鍵盤輸入的字符為字符串,然后對字符串的每個字符進行判斷是否為數字,如果有非數字字符出現則提示出錯並要求重新輸入。又如在判 斷是否繼續時要求輸入Y/N時,按一般的方式,如果輸入為多個字符,則多余的字符會保存在緩沖區,到下次要求輸入時輸入而導致出錯,對此問題設計處理方式 為接受輸入字符保存為串然后只取其首字符進行判斷。還有很多類似的錯誤處理。還有在設置程序的顯示優化時,發現暫停函數在不同的情況下執行順序不同,如此 等等。在課程設計過程中遇到了許多問題,也向同宿舍的同學做了一些請教一起討論,也因此從他們身上學到了許多東西。
