死锁检测
死锁检测监视驱动程序对需要锁定的资源的使用情况 -- 旋转锁、互斥和快速互斥。 此驱动程序验证程序选项将检测在将来某个时间点可能导致死锁的代码逻辑。
驱动程序验证程序的死锁检测选项以及 !死锁 内核调试器扩展是一种有效的工具,可确保代码避免这些资源的不当使用。
死锁检测仅在 Windows XP 和更高版本的 Windows 中受支持。
死锁的原因
当两个或更多线程在某个资源上发生冲突时,会导致 死锁 ,导致无法执行。
当两个或多个线程等待另一个线程拥有的资源时,会发生最常见的死锁形式。 具体说明如下:
线程 1 | 线程 2 |
---|---|
采用锁 A | 采用锁 B |
请求锁定 B | 请求锁定 A |
如果两个序列同时发生,则线程 1 永远不会获得锁 B,因为它由线程 2 拥有,而线程 2 将永远不会获得锁 A,因为它由线程 1 拥有。 这充其数会导致所涉及的线程停止,在最坏时会导致系统停止响应。
死锁不限于两个线程和两个资源。 三个线程和三个锁之间的三向死锁很常见,甚至偶尔会出现五部分或六部分死锁。 这些死锁需要一定程度的“运气不好”,因为它们依赖于同时发生的一些事情。 但是,锁获取距离越远,这些获取的可能性就越大。
当线程尝试获取它已拥有的锁时,可能会发生单线程死锁。
所有死锁的共同点是,不遵循锁层次结构。 每当需要一次获取多个锁时,每个锁都应具有明确的优先级。 如果 A 在一个点之前取 B,另一个点取 B 在 C 之前,则层次结构为 A-B-C。 这意味着不能在 B 或 C 之后获取 A,不得在 C 之后获取 B。
即使不存在死锁的可能性,也应该遵循锁层次结构,因为在维护代码的过程中,很容易意外引入死锁。
可能导致死锁的资源
最明确的死锁是 自有 资源的结果。 其中包括旋转锁、互斥锁、快速互斥锁和 ERESOURCE。
) 事件和 LPC 端口等 (发出信号而不是获取的资源往往会导致更模糊的死锁。 当然,代码会以两个线程最终无限期地等待彼此完成的方式滥用这些资源,而且非常常见。 但是,由于这些资源实际上不归任何一个线程所有,因此无法以任何程度的确定性来识别有问题的线程。
驱动程序验证程序的死锁检测选项查找涉及旋转锁、互斥和快速互斥的潜在死锁。 它不监视 ERESOURCEs 的使用,也不监视非所有者资源的使用。
死锁检测的影响
驱动程序验证程序的死锁检测例程发现不一定同时发生的锁层次结构冲突。 大多数情况下,这些冲突会识别在给定机会时会死锁的代码路径。
为了查找潜在的死锁,驱动程序验证程序会生成资源获取顺序图并检查循环。 如果要为每个资源创建一个节点,并在一个锁之前获取一个锁时绘制箭头,则路径循环将表示锁层次结构冲突。
驱动程序验证程序会在发现其中一个冲突时检查发出 bug。 这将在任何实际死锁发生之前发生。
注意
即使始终无法同时发生冲突的代码路径,如果它们涉及锁层次结构冲突,它们仍应重写。 此类代码是“等待发生的死锁”,如果代码稍作重写,可能会导致真正的死锁。
当死锁检测发现冲突时,它将发出 bug 检查 0xC4。 此 bug 检查 的第一个参数将指示确切的冲突。 可能的冲突包括:
锁层次结构冲突中涉及的两个或多个线程
尝试以独占方式获取其已是共享所有者 (独占资源的资源的线程可以获取共享;不能仅) 获取共享资源。
尝试两次获取相同资源的线程 (自死锁)
在未先获取的情况下释放的资源
一个资源,该资源由与获取它的线程不同的线程释放
多次初始化或根本没有初始化的资源
在仍拥有资源时删除的线程
从 Windows 7 开始,驱动程序验证程序可以预测可能的死锁。 例如,尝试将相同的KSPIN_LOCK数据结构用作常规旋转锁和堆栈排队旋转锁。
有关 bug 检查参数的列表,请参阅 bug 检查0xC4 (DRIVER_VERIFIER_DETECTED_VIOLATION) 。
监视死锁检测
死锁检测发现冲突后,可以使用 !死锁 内核调试器扩展来确切调查已发生的情况。 它可以在最初获取锁时显示锁层次结构拓扑以及每个线程的调用堆栈。
Windows 调试工具包的文档中提供了 !死锁 扩展的详细示例,以及有关调试器扩展的一般信息。 有关详细信息 ,请参阅 Windows 调试 。
激活此选项
注意
此选项与内核同步延迟模糊不兼容
可以使用驱动程序验证程序管理器或 Verifier.exe 命令行为一个或多个驱动程序激活死锁检测功能。 有关详细信息,请参阅 选择驱动程序验证程序选项。
在命令行
在命令行中,死锁检测选项由 位 5 (0x20) 表示。 若要激活死锁检测,请使用标志值0x20或向标志值添加0x20。 例如:
verifier /flags 0x20 /driver MyDriver.sys
下次启动后,该功能将处于活动状态。
在 Windows Vista 和更高版本的 Windows 上,还可以通过将 /volatile 参数添加到 命令来激活和停用死锁检测,而无需重启计算机。 例如:
verifier /volatile /flags 0x20 /adddriver MyDriver.sys
此设置会立即生效,但在关闭或重启计算机时会丢失。 有关详细信息,请参阅 使用易失性设置。
死锁检测功能也包含在标准设置中。 例如:
verifier /standard /driver MyDriver.sys
使用驱动程序验证程序管理器
选择“ ) 为代码开发人员创建自定义设置 ( ”,然后选择“ 下一步”。
从完整列表中选择“选择单个设置”。
选择“ (检查) 死锁检测”。
死锁检测功能也包含在标准设置中。 若要使用此功能,请在驱动程序验证程序管理器中,选择“创建标准设置”。