为什么有时Windows无法终止进程?


30

目前,我正在尝试在Visual Studio中运行/调试应用程序,但由于的最后一个实例app.vshost.exe仍在运行,因此无法创建它。然后,通过使用任务管理器,我试图将其杀死,但它仍然保留在那里而没有任何活动信号。

除了这种特殊情况(可能是Visual Studio错误)之外,我对有时Windows无法终止进程的技术原因非常好奇。

能够与OS相关的开发者,请尝试解释一下吗?

(并且请不要针对Windows发起Unix / Linux / Mac战争。)


10
如果我每次都只有镍,我想回答这个问题……
史蒂芬·奥克斯利

3
我很感谢您的回答,但我想读一位操作系统开发人员,他解释了为什么这个时代的OS不能杀死非核心/内核(或任何合适的形容词)进程。我相信,自386以来,就有一个“环0”(或类似的东西)赋予某些代码相对于其他代码特殊的特权,我认为这是(OS)进程对其他代码具有特权的方式。也许我完全错了,但问题仍然没有答案。
内斯托尔·桑切斯A.

Answers:


21

原因通常是一些未响应的驱动程序未完成 I / O请求。

参见Mark Russinovich的博客文章Unkillable Processes 存档


这也发生在Linux中。尽管x86体系结构具有4个环,但仅使用了两个环(用户空间为3环,内核为0环)。因此,一切都是内核模式或用户空间,两者之间没有任何关系。但是,可能的解决方法是“用户模式”驱动程序,该驱动程序依赖于仅调用用户空间代码的小型可靠内核模式存根。我相信Windows中大多数打印和USB驱动程序都是这种驱动程序(图形驱动程序以前在Windows 3.1中使用),但是用户空间会降低性能。
LawrenceC

业界(英特尔,AMD,ARM等)是否不能创建一个“元环”,以便最终向用户(由自己承担风险)提供杀死进程并一劳永逸地解决该问题的真正能力????
内斯托尔·桑切斯A.

16

一个可能的原因:您无法终止附加到调试器的任务。

停止任务的唯一方法是从调试器本身。


3
我如何确定是否附加了调试器以及附加了哪个进程?因为我没有调试任何东西,但是任务不会死,不是通过任务管理器,不是在停止服务时,不是通过taskkill /f,不是在wmic ... call terminate...,它总是说“错误:带有pid Y的进程X无法终止没有此任务的运行实例。”
卢克,

3

原因之一是您无权杀死它。例如,如果该进程以管理员身份运行并且您是普通用户。


3

打开项目的“ 属性”页面,转到“ 调试”选项卡,然后选中“启用非托管代码调试”。或者,取消选中使用主机进程的选项。



2

我唯一的OS级开发经验是在研究生院学习的,但是我怀疑发生了什么(或类似的事情):

运行调试器尝试处理的最后一个实例时发生错误,但是其他一些问题导致该失败(可能是遇到调试断言,但是在单击对话框以中止/重试/忽略之前,触发了另一个中断,可能是由于空指针造成的)。在停止调试之后,结果是调试器仍在等待您对第一个调试断言的响应,因此它不会使进程终止。但是,当您停止调试(或这样做?)时,调试器终止,将进程变成僵尸,或将其树变成僵尸。当您尝试杀死僵尸进程时,发生了类似于此的错误,但是任务管理器没有告诉您有关它的信息:

C:\Windows\system32>taskkill /pid 9564 /f /t
ERROR: The process with PID 9564 (child process of PID 22520) could not be
terminated.
Reason: There is no running instance of the task.

如果您决定在父级上尝试相同的操作(在我的情况下,父级是调试器进程msvsmon.exe),它将以相同的方式失败:

C:\Windows\system32>taskkill /pid 22520 /f /t
ERROR: The process with PID 9564 (child process of PID 22520) could not be
terminated.
Reason: There is no running instance of the task.
ERROR: The process with PID 22520 (child process of PID 13964) could not be
terminated.
Reason: There is no running instance of the task.

父进程由IDE启动,但是IDE切断了脐带,所以现在您有两个僵尸进程。您无法将调试器附加到正在调试的进程中,因为已经附加了(僵尸)调试器,并且您无法将调试器附加到(僵尸)调试器,因为Visual Studio会在您尝试时告诉您:

无法附加到进程。在当前状态下,操作是非法的。

僵尸程序在进程表中的位置仍然足够好,可以防止您通过调试器运行另一个实例,但是您可以在IDE外部启动另一个实例。

这解决了让VS创建僵尸进程的更具体问题。但是,僵尸进程通常不会消失。好吧,通常是在Windows上,有时是在Linux上,直到您用gun弹枪射击它们。还是那次关机?但是要当心未决的Windows更新应用程序。

我对建议附加到调试器的一些较早的答案感到很兴奋,但是以上是我得到的结果。因此,我要提交答案并重新启动以清理进程表。


谢谢,这无疑是匹配我的问题的最佳答案。
Pablo Ariel's



-1

如果您使用VS来调试过程,并使用任务管理器将其杀死,那么VS将无法很好地处理它。

因此VS仍在调试目标进程,但您不能仅在VS中按Stop进程即可,只需退出VS即可看到进程退出。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.