Windows 如何知道程序没有响应?

Windows 如何知道程序没有响应?

Windows 如何知道某个程序是否没有响应?它是否不断轮询所有正在运行的应用程序?

答案1

应用程序从 Windows 提供的队列中获取事件。

如果应用程序在一段时间内(5 秒)没有轮询事件队列,例如在进行长时间计算时,则 Windows 会假定应用程序已挂起并提醒用户。

为了避免这种情况,应用程序应该将昂贵的计算推送到工作线程或拆分处理并确保定期轮询队列。

答案2

Windows 如何知道程序没有响应?

如果没有 Windows 的源代码,我们就无法确定它内部在做什么。

有一个IsHungAppWindow可以使用的 SDK Windows 函数。

如果应用程序没有等待输入、没有处于启动处理中、也没有调用预览消息在5秒的内部超时期限内。

来源IsHungAppWindow 函数

如果顶级窗口停止响应消息超过几秒钟,系统会认为该窗口没有响应。在这种情况下,系统会隐藏该窗口并将其替换为具有相同 Z 顺序、位置、大小和视觉属性的幽灵窗口。这允许用户移动它、调整它的大小,甚至关闭应用程序。但是,这些是唯一可用的操作,因为应用程序实际上没有响应。

来源关于消息和消息队列


它是否会持续轮询所有正在运行的应用程序?

否。应用程序没有被轮询,但被给予处理器时间。

Windows 有一个调度系统,可以将处理器时间分配给应用程序线程。

调度算法很复杂,完整描述如下Windows Internals,第 1 部分(第 6 版)(开发人员参考)

答案3

实际上,Windows 并不总是知道应用程序没有响应。应用程序必须是与窗口交互的应用程序,并且窗口必须正在接收应用程序无法处理的消息,Windows 才会断定应用程序没有响应。

例如,Windows 无法知道从命令行运行的没有用户界面的数字运算应用程序是否正在执行其工作,或者是否陷入了无限循环。

Windows 中的交互式图形应用程序通过不断轮询消息队列来接收事件。Windows 用键盘、鼠标、计时器等事件填充此消息队列。如果应用程序在一段时间内未能轮询消息队列(IsHungAppWindow() 函数文档中提到的超时时间为 5 秒),Windows 会认为该应用程序“挂起”,它可能会通过更改窗口标题(在本地化版本中添加文本“(无响应)”或等效文本)并在用户尝试与窗口交互时使窗口内容变灰来表示。

应用程序可能会以 Windows 无法识别的方式挂起。例如,应用程序可能会继续轮询其消息队列中的消息,但不会对其采取适当行动,因此,从实际意图和目的来看,应用程序似乎处于“挂起”状态,而 Windows 无法识别它没有响应。

答案4

您的问题的答案是肯定/否定。

虽然 Windows 操作系统可以并且确实会使用 Windows 消息队列中的事件轮询应用程序,但程序绝对没有义务链接到 WinAPI 或处理/应答 Windows 队列。即使应答队列中的消息也无法告诉 Windows 程序是否已“锁定”。它只是一个指示器,但仅此而已。真正的答案要复杂得多。

真正的答案

人们在这里回避实际答案。确定程序是否“没有响应”是“停机问题“,这在计算机科学中是正式不可判定的。简而言之,处理器不能充当第三方观察自己来确定子程序是否陷入无限循环,什么也不做,而是增加一个计数器,该计数器将终止于某个固定的正常数字。这两者都可以被认为是紧密闭合的循环。一个停止,另一个永远不会终止。即使是你,作为一个人,也不知道程序是否真的在响应,特别是如果它处于紧密闭合的循环中——你只知道认为应该(回应)。

从 Windows 的角度来看,这两个循环都是“未响应”。这就是为什么 Windows 让你选择等待还是终止,因为它无法分辨。

因此推论是“为什么 Windows 知道一个进程响应?”答案相当聪明。当一个进程在多线程和多进程操作系统中编译时,有时甚至在紧密闭环中,编译器可能会添加一个屈服()命令,它向处理器提供方便的通知,告知它可以切换到其他正在运行的进程。它“放弃”处理器,并发生“上下文切换”(这是所谓的),允许操作系统(包括 Windows)响应堆栈中的其他事件,其中一些事件包括跟踪进程回应道。

**这并不意味着响应过程将终止。** 无限循环内部的进程可以让出处理器,让 Windows 处理其他事件。

在某些 Windows 程序中,程序将处理 Windows 操作系统信号,这些信号可以告诉操作系统它正在“响应”,但没有任何程序有义务这样做。您可以编写非常简单的占用 CPU 的非终止程序,甚至可以在 Windows 上的高级语言(如 perl、php、python)中编写,而 Windows 可能无法检测到它没有终止和没有响应。此时,Windows 依靠启发式方法(CPU 负载、内存、程序运行时处理器处理的中断数)来“猜测”。同样,此时,Windows 必须要求您终止,因为它真的不知道是否应该终止。

另请参阅 Viktor 的(正确)答案。忽略关于“不响应”是否与无限循环不同的评论。应用程序可能会或可能不会在不通知 Windows 消息队列的情况下处理各种消息、中断、循环。处理消息队列只是操作系统保持计数器以尝试处理的许多事件之一猜测进程是否挂起。

相关内容