我在我们的一台 Windows 8.1 工作站上遇到了一个非常奇怪的问题和解决方案,我无法弄清楚我的解决方案如何解决该问题。
这是工作站:
- Windows 8.1 x64
- AMD 速龙 x64 x2 5200+ 2.7GHz
- 4GB DDR2 内存
- NG1DB-M25 映泰主板
- 1TB 西部数据硬盘
- DVD 驱动器(不确定品牌)
正如您所看到的,除了硬盘和 DVD 驱动器之外,它的硬件都很旧(可能很旧,但直到最近才开始使用,我才把它放进去)。
在发生了一些我无法从用户描述中完全理解的事情(据称与睡眠模式有关)之后,工作站进入了修复循环,我甚至无法将其启动到安全模式,它只是加载并开始尝试自我修复。
我一整天都在忙于处理更重要的事情,所以我就让它运行,第二天它启动正常,但当我尝试打开 Windows 更新时,窗口会打开,但不会加载任何信息,它会挂起,直到我重新启动资源管理器。另一个程序也存在问题,会导致该程序挂起。
我先尝试了DISM.exe /Online /Cleanup-image /Restorehealth
,然后尝试了 SFC。都没有用,所以我决定继续重新格式化。我放入 DVD,当我尝试启动它时,Windows 只出现了一个错误屏幕(我现在记不起任何代码或确切的措辞),表示可拆卸存储存在一些问题。没有 USB 驱动器,所以我认为这一定与 DVD 驱动器有关。我换掉了 SATA 数据线,现在工作站运行正常,不需要重新格式化或做任何事情。
我无法解释这是如何解决问题的。直到最后,问题都不可能归因于 DVD 驱动器,因为它从未被访问过。有谁知道为什么更换 SATA 电缆可以解决所有问题,还是这只是巧合,也可能发生了其他事情?
答案1
当硬件出现故障时,它会导致多种症状。最有可能的是蓝屏死机,但较轻微的症状也很容易出现。为了更好地了解看似不相关的程序如何受到硬件的影响,请考虑操作系统模型:
用户软件 > 内核 > 硬件抽象层 > 硬件
任何想要与任何资源(甚至是 CPU 或 RAM)交互的程序都必须与内核配合,而内核又依赖 HAL 将往返于硬件的各种物理信号转换为往返于内核的逻辑信号。
内核有一些限制来“保证”稳定性,例如有限的可重入性、线程安全性、资源限制等等。特别是,大多数硬件没有共享的概念;这是通过 HAL 或内核驱动程序在更高层次上抽象出来的。
如果您还记得调制解调器的时代,那么每次只有一个程序可以使用调制解调器,例如拨号程序。互联网通过生成一个公共堆栈解决了这个问题——所有想要访问互联网的程序都通过一个公共堆栈进行访问,并且该堆栈对硬件拥有独占控制权。堆栈产生了多路复用以共享这一资源。
即使在今天,声卡、磁盘驱动器、视频卡等也无法物理共享。信号会变得混乱,从而导致混乱。HAL 可以很好地欺骗用户,让他们认为实际上同时有多个任务在进行。仍然存在物理瓶颈,但当硬件按预期工作时,我们通常不会注意到它。
但问题的核心在于,如果 HAL 在与设备通信时出现问题,它可能会因为反复尝试重新发送或重新读取数据而受阻。HAL 通常不是多线程的,因此它每次只能处理一个请求(每个驱动程序链)。
例如,如果磁盘驱动器被锁定,尝试读取损坏的驱动器,则尝试进行类似 API 调用的任何其他程序都将排在被阻止的调用后面,从而可能导致该程序挂起。多线程程序不会出现此问题,因为在驱动器被锁定时 UI 可以保持响应。不幸的是,大多数程序不是多线程。
Windows 中的许多程序基本上都会陷入循环,如下所示:
while(GetMessage(&msg, hWnd, NULL, NULL)) {
DispatchMessage(&msg);
}
您可能已经猜到了,只有一个线程。一旦它尝试读取挂起的驱动器,它就无法恢复,直到驱动器最终超时。如果没有,该程序将受操作系统 API 的支配。但是,即使它是多线程的,驱动器读取线程也会被锁定,尽管 UI 线程能够检测到这种情况并恢复/中止。
使问题更加复杂的是,许多 API 调用(例如分配内存、打开驱动器或文件等的调用)都是阻塞调用。它们会导致当前线程无限期等待(除非它请求特定的超时值),直到操作系统完成请求或因超时而中止请求。大多数程序不会假设操作系统会花费很长时间,因此永远不会指定超时。如果驱动器没有响应,这些程序将永远无法恢复。
对于“从不访问故障驱动器”的程序来说,它不一定非要这样做。它所需要做的就是调用当前被坏驱动器阻止的函数。例如,如果在坏的 DVD 驱动器上调用 OpenFile,那么其他文件请求可能会被挂起,直到 DVD 驱动器超时,即使它们只是从系统驱动器读取。
也许程序调用了 GetOpenFileName,它会显示一个 OS 呈现的对话框,该对话框将接管线程的控制权,直到它返回。该窗口通过枚举驱动器列表列出系统上的所有驱动器。如果 API 挂在坏驱动器上,最终结果是一样的:对话框被冻结,冻结整个应用程序,等待该驱动器可用/空闲。