【操作系统】三千字解析银行家算法例题

背景与设定

一个银行家手握一定数量的钱,有三个人来借。但是这些钱不够一次性全部满足借贷者,所以需要合理安排借贷顺序,按顺序满足借贷者,且最终收回的钱数和开始拥有的钱相同。(每名借贷者只有总需求全部满足时,才会一次性把这些钱都还给银行家;没有利息)

将这种设定平移到OS给各进程分配资源。值得注意的是,钱只是一种资源,但OS中有多种种类的资源,将单个的数字改为向量(数组)表示各资源数量,如(1,2,3)表示三类资源的数目分别是1,2,3:

Max数组:各进程所需要的最大资源数目。这个数目在整道题目中不变

Allocation数组:各进程分配到的资源数目。在初始时刻,各资源已分配到一定的资源。在OS分配资源的过程中,Allocation的值会随新分配资源而变化

Max数组:Need=Max-Allocation,即系统仍需要的最大资源数目。

Available数组:初始时刻时,OS的可用资源数目。Available+初始时刻Allocation=OS可用资源数目。OS可用资源总数目的初始值和成功分配给全部进程并收回资源后的值是相等的,可用于检查计算对错。

Work数组:除了初始时刻外的每一时刻,OS的可用资源数目。在安全检查算法中,只出现Work,不出现Available。事实上,有些课本认为每一时刻的OS可用资源数目都为Available,本文按照汤小丹《计算机操作系统》书写这部分内容,认为只有初始时刻的OS可用资源数目为Available。

Request数组:有时候,进程并非只是等待Need被满足,而是会提出对各资源的新申请。

Finishi数组:布尔变量,成功分配到全部资源的进程的Finish置为true,各进程的Finish初值都为false

题型与细节

补充一下上述向量大小的判断:一个小就都小,有分量大有分量相等但没有小于就是大于,各分量都相等才相等。如(4,2,0)>(1,1,0),(5,8,1)<(4,3,9)

判断初始时刻系统是否处于安全状态: 检查是否存在一个安全序列,即按照该顺序可依次满足各进程的需求。安全序列一般不唯一,找到一个就行。判断步骤:

银行家算法是一种用于避免死锁的资源分配算法。它通过安全性检查来确定系统是否处于安全状态,以确保分配资源不会导致死锁的发生。下面是银行家算法中的安全性检查步骤:

  1.    找到一个未完成的进程P,满足以下条件:P的需求量Need[i] <= Available[i],对于所有的资源类型i。 如果满足上述条件,则假设P执行完毕并释放它所占有的资源。
  2.    将P释放的资源添加到Available中。
  3.   重复步骤1和2,直到找不到满足条件的进程。

图中用下标k表示序号为k的进程的相关向量

 如果所有进程都能够找到满足条件的执行顺序,则系统处于安全状态;否则,系统处于不安全状态。

Request申请可能合理也可能不合理,分两步判断:先判断Request\leq Need是否成立,即进程申请的资源数目不能大于进程所需的最大资源数目;若成立,再判断Request\leq Available是否成立,即进程申请的最大资源数目不能大于系统该时刻的可用资源数目(认为分配那一刻为初始时刻)。

Request合理也不一定能分配,因为分配后的系统可能处于不安全状态。先假装分配(即进行预分配),将分配后这一刻作为初始状态,利用安全性算法进行检查发,若能找到一个安全序列,说明系统处于安全状态,可以立即分配。

例题与解析

OS中三类资源总量为(10,5,7),T0时刻资源分配情况如表:

MaxAllocationNeedAvailable
P0(7,5,3)(0,1,0)(7,4,3)(3,3,2)
P1(3,2,2)(2,0,0)(1,2,2)
P2(9,0,2)(3,0,2)(6,0,0)
P3(2,2,2)(2,1,1)(0,1,1)
P4(4,3,3)(0,0,2)(4,3,1)

Available=总量-Allocation=(10,5,7)-[(0,1,0)+(2,0,0)+(3,0,2)+(2,1,1)+(0,0,2)]=(3,3,2),计算结果填入表中。

(1)判断T0时刻的安全性

分析:(3,3,,2)<(1,2,2),先分(1,2,2)给P1,P1用完了把自身占用的全部资源还给OS,OS有(3,3,2)+(2,0,0)=(5,3,2)新分出去的又还回来,一减一加不变,进程还回后的OS资源持有量=新分前的资源持有量+新分前的进程资源持有量即work=work(available)+allocation。(5,3,2)>(0,1,1),给P3,P3用完还给OS,OS有(5,3,2)+(2,1,1)=(7,4,3);(7,4,3)=(7,4,3),全给P0,P0用完还给OS,OS有(7,4,3)+(0,1,0)=(7,5,3);(7,5,3)>(6,0,0),给P2,P2用完还OS,OS有(7,5,3)+(3,0,2)=(10,5,5);(10,5,5)>(4,3,1),给P4,P4用完还OS,OS有(10,5,5)+(0,0,2)=(10,5,7),与题干所给值相等,计算正确,存在安全序列{P1,P3,P0,P2,P4},系统安全。

解题过程:利用安全性算法对系统资源分配情况进行检查:

WorkNeedAllocationWork+AllocationFinish
P1(3,3,2)(1,2,2)(2,0,0)(5,3,2)true
P3(5,3,2)(0,1,1)(2,1,1)(7,4,3)true
P0(7,4,3)(7,4,3)(0,1,0)(7,5,3)true
P2(7,5,3)(6,0,0)(3,0,2)(10,5,5)true
P4(10,5,5)(4,3,1)(0,0,2)(10,5,7)true

存在安全序列{P1,P3,P0,P2,P4},故系统安全 

(2) 若P1请求资源(1,0,2),能否分配?

(1,0,2)<(1,2,2)且(1,0,2)<(3,3,2),可进行预分配
预分配后初始时刻变为:

MaxAllocationNeedAvailable
P0(7,5,3)(0,1,0)(7,4,3)(2,3,0)
P1(3,2,2)(3,0,2)(0,2,0)
P2(9,0,2)(3,0,2)(6,0,0)
P3(2,2,2)(2,1,1)(0,1,1)
P4(4,3,3)(0,0,2)(4,3,1)

同(1)中的安全性算法检查如下

WorkNeedAllocationWork+AllocationFinish
P1(2,3,0)(0,2,0)(3,0,2)(5,3,2)true
P3(5,3,2)(0,1,1)(2,1,1)(7,4,3)true
P4(7,4,3)(4,3,1)(0,0,2)(7,4,5)true
P2(7,4,5)(6,0,0)(3,0,2)(10,4,7)true
P1(10,4,7)(7,4,3)(0,1,0)(10,5,7)true

存在安全序列{P1,P3,P4,P2,P1},系统安全,可以立即将资源(1,0,2)分配给P1  

(3)在(2)的基础上,P4请求资源(3,3,0),能否分配?

(3,3,0)<(4,3,1)但(2,3,0)<(3,3,0),不能分配

本题节选自课本例题,原文没有红字但通过其步骤,显然是在上一问的基础上进行的。在各小问中,若某一问的判断结果是按申请分配后系统处于安全状态,则后续小问默认在此基础上进行。在正式考试中,每个关于申请资源的小问前一般会注明“在上一问的基础上”

还有一种常见的不能进行分配的情况是: 预分配后,Available不能满足任何进程的Need

  • 20
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
银行家算法用于避免死锁,确保系统资源的分配是安全的。下面是一个简单的银行家算法的C语言代码实现,该代码实现了以下函数: - `request_resources()`:请求资源 - `release_resources()`:释放资源 - `is_safe()`:判断当前状态是否安全 注意,这里的资源是指系统中的各种资源,如内存、I/O设备等。每个进程都会请求一定数量的资源,并在使用完这些资源后释放它们。 ```c #include <stdio.h> #define MAX_PROCESSES 10 #define MAX_RESOURCES 10 int available[MAX_RESOURCES]; int maximum[MAX_PROCESSES][MAX_RESOURCES]; int allocation[MAX_PROCESSES][MAX_RESOURCES]; int need[MAX_PROCESSES][MAX_RESOURCES]; int num_processes; int num_resources; int request_resources(int pid, int request[]) { int i; for (i = 0; i < num_resources; i++) { if (request[i] > need[pid][i]) { return -1; } if (request[i] > available[i]) { return -1; } } for (i = 0; i < num_resources; i++) { available[i] -= request[i]; allocation[pid][i] += request[i]; need[pid][i] -= request[i]; } if (is_safe()) { return 0; } else { for (i = 0; i < num_resources; i++) { available[i] += request[i]; allocation[pid][i] -= request[i]; need[pid][i] += request[i]; } return -1; } } int release_resources(int pid, int release[]) { int i; for (i = 0; i < num_resources; i++) { available[i] += release[i]; allocation[pid][i] -= release[i]; need[pid][i] += release[i]; } return 0; } int is_safe() { int i, j, k; int work[MAX_RESOURCES]; int finish[MAX_PROCESSES]; for (i = 0; i < num_resources; i++) { work[i] = available[i]; } for (i = 0; i < num_processes; i++) { finish[i] = 0; } for (i = 0; i < num_processes; i++) { if (finish[i] == 0) { for (j = 0; j < num_resources; j++) { if (need[i][j] > work[j]) { break; } } if (j == num_resources) { finish[i] = 1; for (k = 0; k < num_resources; k++) { work[k] += allocation[i][k]; } i = -1; } } } for (i = 0; i < num_processes; i++) { if (finish[i] == 0) { return 0; } } return 1; } ``` 在上面的代码中,`available`数组表示每个资源当前可用的数量;`maximum`数组表示每个进程最多需要的每个资源的数量;`allocation`数组表示每个进程已分配的资源数量;`need`数组表示每个进程还需要的资源数量。 `request_resources()`函数用于请求资源。如果请求的资源超过了进程所需要的资源数量或者超过了当前可用的资源数量,该函数将返回-1,表示请求失败。否则,该函数将分配请求的资源,并调用`is_safe()`函数判断当前状态是否安全。如果是安全的,该函数将返回0,否则将释放分配的资源,并返回-1。 `release_resources()`函数用于释放资源。该函数将释放进程已分配的资源,并更新`available`、`allocation`和`need`数组。 `is_safe()`函数用于判断当前状态是否安全。该函数首先初始化`work`数组为当前可用的资源数量,`finish`数组为0。然后对于每个未完成的进程,检查它是否需要的每个资源数量都小于等于`work`数组中的相应资源数量。如果是,将该进程标记为完成,并将它已分配的资源释放到`work`数组中。如果所有进程都完成了,返回1,否则返回0。 在实际使用中,需要根据具体情况修改上面的代码。例如,可以在`request_resources()`和`release_resources()`函数中添加一些输出语句,以便调试和测试。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值