📜  操作系统中的银行家算法(1)

📅  最后修改于: 2023-12-03 15:39:52.965000             🧑  作者: Mango

操作系统中的银行家算法

简介

银行家算法是操作系统中常用的一种死锁(Deadlock)避免算法。死锁是指进程因为互相等待资源而陷入的一种无限期阻塞状态。当一个进程请求资源时,系统会分配这个进程请求到的资源,如果分配后系统仍然处于安全状态即不会导致死锁的发生,那么就分配资源。银行家算法的基本思想就是在进行资源分配的时候对系统状态进行检查,以避免进程进入死锁状态。

示例

为了方便展示银行家算法,下面我们将设计一个简化版的银行家系统。我们假设该系统中有5个进程,每一个进程需要访问3个资源。该系统拥有10个资源。我们将会记录每个进程最初的申请资源数,以及每个进程当前占用的资源数和仍需要的资源数。

# 记录银行家系统资源情况
total_res = 10
# 初始化每个进程申请资源数,有5个进程
proc_req = [[3, 3, 2], [2, 0, 0], [3, 0, 2], [2, 1, 1], [0, 0, 2]]
# 初始化每个进程占用资源数
proc_used = [[0, 0, 0], [2, 0, 0], [3, 0, 2], [0, 1, 1], [0, 0, 2]]
# 初始化每个进程仍需要的资源数
proc_need = [[3, 3, 2], [0, 0, 0], [0, 0, 0], [2, 0, 0], [0, 0, 0]]

这五个进程的资源情况可以用一个表格来表示:

| 进程编号 | 初始申请资源数 | 占用资源数 | 仍需要资源数 | | ---- | ---- | ---- | ---- | | 0 | 3, 3, 2 | 0, 0, 0 | 3, 3, 2 | | 1 | 2, 0, 0 | 2, 0, 0 | 0, 0, 0 | | 2 | 3, 0, 2 | 3, 0, 2 | 0, 0, 0 | | 3 | 2, 1, 1 | 0, 1, 1 | 2, 0, 0 | | 4 | 0, 0, 2 | 0, 0, 2 | 0, 0, 0 |

现在,如果进程1请求1个资源,进程4请求2个资源,询问以下资源状态是否安全。

这时候,我们可以编写一个 check_safe 函数来进行检查是否安全。

def check_safe():
    """
    检查当前状态是否安全
    """
    # 复制当前占用资源数、仍需要资源数
    work = [i for i in total_res]
    finish = [False for _ in range(len(proc_used))]
    # 初始化安全序列为空
    safe_seq = []
    # 循环直到找到所有进程的安全序列或者当前状态不可用
    while not all(finish):
        # 查找可以满足当前需求的进程
        can_finish = False
        for i in range(len(proc_used)):
            if not finish[i] and all([proc_need[i][j] <= work[j] for j in range(len(work))]):
                can_finish = True
                finish[i] = True
                safe_seq.append(i)
                for j in range(len(work)):
                    work[j] += proc_used[i][j]
                break
        # 如果当前状态不能满足任意一个进程,说明状态不可用,直接退出
        if not can_finish:
            return False, []
    return True, safe_seq

通过银行家算法检查当前状态是否安全的流程是:

  1. 假设当前状态是安全的,将每个进程的完成状态设为 False
  2. 复制当前占用资源数作为可用资源数。安全序列为空。
  3. 循环,找到所有可以完成的进程,并按照顺序将其进程编号添加到安全序列中。如果没有可以完成的进程,则跳到步骤5。
  4. 将已经完成的进程占用的资源数返还到可用资源数中。
  5. 检查是否所有进程都能够完成。如果有为完成的进程,则说明当前状态不安全。

现在我们运行一下上面的 check_safe() 函数:

print(check_safe())

得到的结果应该是 (True, [1, 3, 4, 0, 2]),即当前状态是安全的,安全序列为 1, 3, 4, 0, 2。这个序列的意思是,依次完成进程 1、3、4、0 和 2,就能保证整个系统状态是安全的。

按照现在的资源分配结果,进程占用资源的情况为:

| 进程编号 | 初始申请资源数 | 占用资源数 | 仍需要资源数 | | ---- | ---- | ---- | ---- | | 0 | 3, 3, 2 | 1, 1, 0 | 2, 2, 2 | | 1 | 2, 0, 0 | 3, 0, 0 | 0, 0, 0 | | 2 | 3, 0, 2 | 3, 0, 2 | 0, 0, 0 | | 3 | 2, 1, 1 | 0, 1, 1 | 2, 0, 0 | | 4 | 0, 0, 2 | 1, 0, 3 | 0, 0, 0 |

再次运行 check_safe() 函数,得到的结果为 (False, []),说明此时状态不安全,无法保证整个系统状态是安全的,不能进行资源分配。

总结

银行家算法是一种非常实用的避免死锁的算法。它可以有效地避免死锁的发生,提高了操作系统的稳定性和可靠性。在实际应用中,我们可以通过合理的资源管理,来避免出现死锁的情况,保证系统的健康运行。