返回

文章详情

理解规避规则时背后的理由

Hacker News2026年6月16日 07:35

在关于实现与进程和线程相关的回调函数最佳实践的文档中,提到要“保持例程简短和简单”。“不要调用用户模式服务来验证进程、线程或图像。” “不要进行注册表调用。” “不要进行阻塞和/或进程间通信(IPC)函数调用。” “不要与其他线程同步,因为这可能导致重入死锁。” 截至目前为止,这些都很好。似乎这些回调函数需要快速操作,并且不能阻塞。这些回调是在进程启动或退出、线程启动或退出、DLL或EXE被加载或卸载,以及其他各种低级事件时调用的各种回调。这些禁止事项表明,这些调用是在进程创建/终止序列中调用的,所以如果你花很长时间来处理它们,你就是在减慢整个系统的速度。而且像“不要进行注册表调用”这样非常严格的要求表明,它们甚至可能在系统保持内部锁时被调用。最佳实践的列表继续:“使用系统工作线程来排队工作,尤其是涉及:缓慢的API或调用其他进程的API。任何可能中断核心服务线程的阻塞行为。” 好吧,这提供了一个建议,告诉你如何将耗时的工作卸载到回调外部的代码中。这再次强调回调本身需要快速,并且最小化阻塞。我在企业支持方面的同事经常遇到系统挂起的情况,而根本原因是驱动程序违反了这些回调必须快速返回的规则。例如,一个常见的反模式是一个驱动程序,其回调开始时遵循上述指导,将工作排队到系统工作线程,但随后它们会一直阻塞,直到工作项完成。这是一种遵循规则而不理解规则存在原因的情况。规则是回调需要快速并且迅速返回。该驱动程序通过将工作委派给系统工作线程遵循了法律的字面意思,并且没有规则说“不要等待工作项”,所以他们必须认为这给了他们执行同步长时间工作的漏洞。但是规则“不要进行阻塞和/或进程间通信(IPC)函数调用”和“不要与其他线程同步,因为这可能导致重入死锁”明确表示,你不应该在回调中长时间阻塞。“不要”只是提出了一些常见的回调可能会阻塞的方式。而且文档在2020年进行了更新,指出了这个特定的案例:“如果你使用系统工作线程,不要等待工作完成。这样做会违背将工作异步完成的目的。”可以说这个规则已经被“不要与其他线程同步”的规则涵盖了,但我想驱动程序供应商理解为“但我并没有与另一个线程同步。我是在事件上同步!”当然,事件是由另一个线程设置的,所以你实际上是在与另一个线程同步。我在企业支持方面的同事将此描述为“不是我,是我兄弟”的借口。你被父母告知不要打开电视,所以你告诉你的兄弟去做。技术上来说,你并没有打开电视,但实际上,你做到了,因为你的兄弟是在你的指示下行动。(这就是为什么合同往往包含“不得披露或导致披露”这样的措辞,以便你不能说“没有,我绝对没有披露。我把信息给了鲍勃,是鲍勃披露的!”。)文档应该以这样的内容开头:回调函数必须迅速执行其工作而不进行阻塞。如果你需要执行复杂的工作或与其他线程或进程同步,请异步处理,例如使用系统工作线程。然后可以给出一系列被视为阻塞的示例。以下是回调函数中不允许的阻塞示例:然后可以跟进其他限制。此外,回调函数不得执行以下任何操作:作者雷蒙德参与了Windows的发展超过30年。2003年,他开始了一个名为“老新事物”的网站,该网站的受欢迎程度远超他的想象,这一发展至今仍让他感到恐惧。该网站催生了一本书,恰好也叫《老新事物》(Addison Wesley 2007)。他偶尔会出现在Windows Dev Docs的Twitter账户上,讲述一些没有实际信息的故事。

赞助内容

NordVPN Next-gen Antivirus

本站免费、广告极少。如果觉得有帮助,可以请我们喝杯咖啡 —— 任何金额都对持续运营有实际帮助。

请我喝杯咖啡