一段时间以来,我在 Windows XP 中遇到SVCHOST.EXE
启动时间歇性崩溃的情况。由于它是间歇性的,我无法可靠地重现它,也无法缩小启动时间,而且由于它是SVCHOST
,我无法确定哪个服务是崩溃的服务,因为该对话框是由创建的CSRSS.EXE
,而不是由的任何实例创建的SVCHOST.EXE
。
有一件事我很确定,那就是如果我关闭发生这种情况时弹出的以下对话框,那么整个系统就会完全挂起,但如果我不理会这个对话框,我可以继续工作并正常使用操作系统,然而在关机时(此时对话框不可避免地会关闭),系统就会挂起,导致需要重置。
我采纳了 Anonymous Coward 的建议,将每个服务设置为使用自己的实例,SVCHOST
而不是共享实例,结果让我吃惊的是,崩溃的进程并不是实例之一SVCHOST
。而是CSRSS.EXE
。
现在,我只能试图弄清楚为什么CSRSS
有时会崩溃(绝大多数包含文件名的搜索只会返回那些毫无价值的基本分析页面),但我不确定如何在没有混乱的内核调试器的情况下调试系统如此不可或缺的一部分。(我要指出的是,系统没有 BSOD,因此没有生成转储。)
有一件事是,地址似乎总是是一样的。这种情况已经发生过十几次了,有问题的指令总是在 处,它0x76dea383
试图读取 处的内存0x00000000
。显然目标内存地址是无用的,但我确信一定有办法以某种方式使用源地址。
发生这种情况时,我尝试关闭所有进程并停止所有可能的服务。不幸的是,这无助于缩小原因范围,因为对话框仍然显示,因为它是由csrss
无法停止的(除非完全关闭整个操作系统)创建的。
旧信息:
我曾尝试找出哪个服务是罪魁祸首,但没有成功。例如,上次发生这种情况时,我停止了所有可能的服务(以及一些通常不可能的服务),退出了每个应用程序,关闭了 Explorer,并将系统基本精简到最低限度(可能还剩下 10 个进程,使用 ~111MB RAM 和 0% CPU),但关闭对话框后它仍然挂起。这让我怀疑它是关键的系统服务之一,但如果是的话,那么系统为什么会在此期间继续运行?
有人知道我可以调试这个吗?例如,有人能想出一种方法来确定SVCHOST
与错误相关的实例吗?我检查了事件日志和进程资源管理器,但没有找到任何可以帮助查明错误的方法。我可以用内存地址做些什么吗?
(是的,我在 Google 上搜索过,发现很多地方提到了 Windows 更新服务,但事实并非如此,因为默认情况下WUAUSVC
和BITS
被禁用。而且,我无法做到禁用所有服务并逐一启用测试方法,因为如果它是关键系统服务之一,那么 Windows 根本无法运行。
答案1
这看起来是个很难解决的问题。你基本上列出了我建议的所有方法(停止服务、事件日志、进程资源管理器……)。我能想到的唯一其他解决方案是像重新安装 Windows 这样的繁琐方法。
然而,这个答案链接到类似的问题微软知识库关于SVCHOST
使用“Windows 调试工具”,也许这可能会有用。
答案2
在回复错误消息之前,请在任务管理器中找出进程 ID (PID),然后在命令提示符下运行tasklist /svc
以找出该进程 ID (PID) 下正在运行的服务。您可能在一个 svchost 实例下运行了 20 个服务,但您可能很幸运,只有一两个。
注意:您可能必须通过消除找出正确的进程ID,即运行任务列表命令,回答错误消息,然后再次运行任务列表以查看哪个进程消失了。
答案3
转储特定服务的方法有多种:
使用调试诊断工具(DebugDiag)1.2。
使用以下批处理文件:
FOR /F "tokens=2 delims=," %%A IN ('tasklist /svc /FI "services eq winmgmt" /NH /FO csv') DO SET PID=%%~A adplus.exe -hang -p %PID% -o c:\dumps
要隔离这些服务,有两种方法,但两者之间只有细微的差别。第一种方法是创建一个隔离进程,该进程在与以前相同的 SVCHOST 组中运行,但不在共享进程中运行。第二种方法是创建一个完全独立的 SVCHOST 组。由于我们一直使用 Windows 更新作为示例,因此我们继续使用这种方法。
方法 1:创建隔离进程
此方法实际上的作用是将相关服务的注册表参数之一从共享进程修改为隔离进程。命令语法相当简单,使用 sc config 命令集:
sc config <service name> type=own
因此对于 Windows 更新(wuauserv),命令将是:
sc config wuauserv type= own
请注意,在“=”和“own”之间有一个空格 - 您必须插入该空格。在后台,发生的情况是 注册表值从(表示共享进程)
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\wuauserv\Type
更改为(表明它有自己的进程)。您可以在 MSDN 文章“SERVICE_STATUS_PROCESS 结构”中阅读有关这些特定值的更多信息。为了完成更改,您需要停止并重新启动该服务。要将此服务更改回共享服务,请运行以下命令:sc config wuauserv type= share。要完成此更改,需要重新启动机器本身。没有修改与此服务相关的任何其他参数,但是当您将类型更改为隔离、重新启动服务,然后运行 tasklist 命令以获取服务列表时,您会注意到有一个 SVCHOST.EXE 进程仅包含 Windows 更新服务。0x20
0x10
方法 2:创建隔离服务组
此方法稍微复杂一些,需要直接编辑注册表。请记住在进行任何更改之前备份注册表!过程如下:
在该键中创建一个名为 WindowsUpdates 的新 REG_MULTI_SZ 值
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Svchost
。将服务名称(本例中为 wuauserv)添加到值中。您还需要从值列表中删除 wuauserv
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Svchost\Netsvcs
以防止冲突。现在导航到该
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\wuauserv
键并将 ImagePath 值从 更改%systemroot%\system32\svchost.exe -k netsvcs
为:%systemroot%\system32\svchost.exe -k WindowsUpdates
重新启动自动更新服务,您现在应该会看到一个仅包含自动更新服务的 SVCHOST.EXE 的新实例。
可以重复此方法以将多个服务隔离到各自的组中。
要恢复到原始配置,请反向执行上述步骤并重新启动计算机。使用注册表备份确保将正确的服务恢复到正确的组中。
此方法的另一种改进是创建 SVCHOST.EXE 的副本,并以适当的名称命名隔离服务 - 例如复制
%systemroot%\system32\svchost.exe
到名为 的新文件%systemroot%\system32\svchost_wuauserv.exe
。请记住,您需要对注册表中的 ImagePath 值进行适当的修改,以反映可执行文件的名称。通过自定义可执行文件,您可以使用我们在之前的文章中介绍过的调试诊断工具包等工具来监控特定服务是否崩溃。您还可以快速判断任务管理器中哪些服务出现故障,并在服务崩溃时获取事件查看器中记录的失败可执行文件的名称。
答案4
故障排除步骤
好吧,我已经尽可能地缩小了范围(再次强调,没有借助内核调试):
- 我检查了服务干净启动后立即管理单元(
services.msc
)编译在正常启动期间运行的所有服务的列表(我已经将其降至最低,所以这肯定有帮助) - 作为匿名懦夫建议,我配置了每个运行的服务在自己的进程中运行
- 下次再发生这种情况时,我会逃跑进程探索器并查看了加载的图像(
Properties->Threads
)CSRSS.exe
- 制作了线程及其图像文件的列表
- 转储每个堆栈
- 下一次,当它再次发生时,我观察了它发生的那一刻以及当时正在发生的事情以及屏幕上的变化
观察结果
CSRSS
这是从步骤 3.1 开始 在过程中运行的图像列表:
winsrv.dll
csrsrv.dll
ati2mtag.sys
在步骤 4 中,我注意到就在错误对话框弹出的同时,一些托盘图标消失了,具体来说,就是来自 ATI Tray Tools 的指示我的显卡温度的图标。
结果
它就在那里!错误对话框弹出后,ATI Tray Tools 崩溃并消失。(我之前怎么没注意到?特别是因为我经常使用热键来调整屏幕亮度。)这与出现在有问题的ATI2MTAG
进程的线程列表中以及定期和重复系统日志条目指出\SystemRoot\System32\ativvaxx.dll failed to load.
摘要/解决方案
如果其他人有类似的问题,找到这里,问题出在 ATI 视频驱动程序上。如果您无法升级硬件,那么也许更新至最新服务包适用于 Windows 的可以修复此问题。(现在,我只需要设置所有合适的服务恢复到共享进程模式—备份文件在哪里.REG
……)