📜  死锁系统模型

📅  最后修改于: 2021-09-27 22:48:32             🧑  作者: Mango

概述 :
当一组进程因为每个进程都持有一个资源并等待另一个进程获取另一个资源而停滞时,就会发生死锁。例如,在下图中,进程 1 持有资源 1,而进程 2 获取资源 2,进程 2 正在等待资源 1。

系统型号:

  • 出于死锁讨论的目的,系统可以建模为有限资源的集合,这些资源可以分为不同类别并分配给各种进程,每个进程都有不同的要求。
  • 内存、打印机、CPU、打开的文件、磁带驱动器、CD-ROM 和其他资源都是资源类别的示例。
  • 根据定义,一个类别中的所有资源都是等价的,并且该类别中的任何资源都可以平等地满足来自该类别的请求。如果情况并非如此(即,如果一个类别内的资源之间存在某种差异),则必须进一步细分该类别。例如,术语“打印机”可能需要细分为“激光打印机”和“彩色喷墨打印机”。
  • 某些类别可能只有一种资源。
  • 内核会跟踪哪些资源是空闲的,哪些已分配,它们被分配给了哪个进程,以及等待该资源可供所有内核管理资源使用的进程队列。互斥体或 wait() 和 signal() 调用可用于控制应用程序管理的资源(即二进制或计数信号量。)
  • 当集合中的每个进程都在等待当前分配给该集合中另一个进程的资源时,该集合被称为死锁。

操作:
在正常操作中,进程必须在使用资源之前请求资源并在完成后释放资源,如下所示。

  1. 要求 –
    如果不能立即授予请求,则进程必须等待所需资源变为可用。例如,系统使用函数 open()、malloc()、new() 和 request()。
  2. 采用 –
    该过程使用资源,例如打印到打印机或读取文件。
  3. 发布 –
    进程放弃资源,允许其他进程使用它。

必要条件:
为了实现死锁,必须满足以下四个条件。

  1. 互斥——
    至少一种资源必须处于不可共享状态;如果另一个进程请求它,它必须等待它被释放。
  2. 保持并等待
    一个进程必须至少持有一个资源,同时还要等待另一个进程当前持有的至少一个资源。
  3. 无抢占——
    一旦一个进程持有一个资源(即在它的请求被授予之后),在该进程自愿释放它之前,不能从该进程中取走该资源。
  4. 循环等待
    必须有一组进程 P0, P1, P2,…, PN 使得每个 P[I] 都在等待 P[(I + 1)% (N + 1)]。 (需要注意的是,这个条件意味着保持等待条件,但如果将这四个条件分开考虑,处理起来会更容易)。

处理死锁的方法:
一般来说,处理死锁的方法有以下三种。

  1. 通过避免让系统陷入循环来防止或避免死锁。
  2. 死锁的检测和恢复,当检测到死锁时,中止进程或抢占一些资源。
  3. 完全忽略问题。
  4. 为避免死锁,系统需要有关所有进程的更多信息。系统尤其必须了解进程将来会或可能会请求哪些资源。 (根据算法,这可以从简单的最坏情况最大值到每个进程的完整资源请求和释放计划。)
  5. 死锁检测相对简单,但死锁恢复需要中止进程或抢占资源,这两者都不是一个有吸引力的选择。
  6. 如果没有避免或检测到死锁,系统将逐渐变慢,因为更多的进程陷入等待死锁阻塞的资源和其他等待进程的状态。不幸的是,当实时进程的计算要求很高时,这种减速可能与一般系统减速相混淆。

死锁预防:
通过避免以下四个必要条件中的至少一个,可以避免死锁:

条件 1 :
互斥:

  • 例如,只读文件不会导致死锁。
  • 不幸的是,某些资源(例如打印机和磁带驱动器)需要单个进程才能对其进行独占访问。

条件 2 :
保持并等待:
为了避免这种情况,必须防止进程持有一个或多个资源同时等待一个或多个其他资源。这里有几种可能性:

  • 要求所有进程同时请求所有资源。如果进程在执行初期需要一种资源,但直到很晚才需要另一种资源,这可能会浪费系统资源。
  • 持有资源的进程必须在请求新资源之前释放它们,然后在单个新请求中重新获取已释放资源和新资源。如果进程使用资源来部分完成操作,然后在释放后无法重新分配它,这可能是一个问题。
  • 如果一个进程需要使用一个或多个流行资源,上述任何一种方法都可能导致饥饿。

条件 3 :
无抢占:
如果可能,抢占进程资源分配有助于避免死锁。

  • 一种方法是,如果一个进程在请求新资源时被迫等待,则该进程先前持有的所有其他资源将被隐式释放(抢占),迫使该进程在单个请求中重新获取旧资源和新资源,如前所述。
  • 另一种方法是,当一个资源被请求而它不可用时,系统会查看当前正在使用这些资源的其他进程,并在等待另一个资源时被阻塞。如果发现了这样的进程,它们的一些资源可能会被抢占并添加到该进程正在寻找的资源列表中。
  • 这些方法中的任何一种都可能适用于状态可以轻松保存和恢复的资源,例如寄存器和内存,但它们通常不适用于其他设备,例如打印机和磁带驱动器。

条件 4 :
循环等待:

  • 为避免循环等待,对所有资源进行编号并坚持进程请求资源严格按递增(或递减)顺序排列。
  • 换句话说,在请求资源 Rj 之前,进程必须首先释放所有 Ri,使得 I >= j。
  • 在这个方案中,各种资源的相对排序是一个重大挑战。

死锁避免:

  • 死锁避免背后的一般思想是通过避免上述条件中的至少一种来避免死锁。
  • 这需要有关每个过程的更多信息,并导致设备利用率低。 (这是一种保守的方法。)
  • 调度程序只需要知道进程在某些算法中可能使用的每个资源的最大数量。在更复杂的算法中,调度器还可以使用调度来确定需要哪些资源以及以什么顺序。
  • 当调度程序确定启动进程或授予资源请求将导致未来的死锁时,进程不会启动或请求被拒绝。
  • 可用和已分配资源的数量,以及系统中所有进程的最大需求,定义了资源分配状态。

死锁检测:

  • 如果无法避免死锁,另一种方法是检测它们并以某种方式恢复。
  • 除了不断检查死锁对性能造成的影响外,还必须有用于从死锁中恢复的策略/算法,并且当进程必须中止或抢占其资源时,可能会丢失工作。

从死锁中恢复:
摆脱束缚有三种基本方法:

  1. 通知系统运算符并允许他/她手动干预。
  2. 停止参与死锁的一个或多个进程。
  3. 防止资源的使用。

从死锁中恢复的方法:
在这里,我们将讨论从死锁中恢复的方法如下。

方法一:
进程终止:
有两种基本的方法来恢复分配给终止进程的资源,如下所示。

  1. 停止参与死锁的所有进程。这确实打破了僵局,但代价是终止了比绝对必要的更多的进程。
  2. 进程应该一次终止一个,直到死锁被打破。这种方法比较保守,但是需要在每一步之后都进行死锁检测。

在后一种情况下,许多因素会影响接下来终止哪些进程,如下所示。

  1. 过程中的优先事项
  2. 流程运行了多长时间以及距离完成有多近。
  3. 这个过程有多少资源和什么样的资源? (它们是否易于预测和恢复?)
  4. 完成该过程还需要多少资源?
  5. 必须杀死多少进程?
  6. 过程是批处理的还是交互式的。

方法2:
资源抢占:
在分配资源以打破僵局时,必须解决三个关键问题:

  1. 选择受害者——
    上面概述的许多决策标准适用于确定从哪些进程中抢占哪些资源。
  2. 回滚——
    理想情况下,被抢占的进程应该在资源最初分配给进程之前回滚到安全状态。不幸的是,确定这样的安全状态可能很困难或不可能,因此唯一安全的回滚是从头开始。 (换句话说,停止并重新启动该过程。)
  3. 饥饿——
    您如何确保进程不会因为其资源不断被抢占而饥饿?一种选择是使用优先级系统并在其资源被抢占时提高进程的优先级。它最终应该获得足够高的优先级,使其不再被抢占。