Localizando o processo com falha
Antes de localizar o processo com falha, verifique se você está no contexto do processador que aceita. Para determinar o processador de aceitação, use a extensão !pcr em cada processador e procure o processador para o qual um manipulador de exceção foi carregado. O manipulador de exceção do processador de aceitação tem um endereço diferente de 0xFFFFFFFF.
Por exemplo, como o endereço de NtTib.ExceptionList neste processador é 0xFFFFFFFF, este não é o processador com o processo com falha:
0: kd> !pcr
PCR Processor 0 @ffdff000
NtTib.ExceptionList: ffffffff
NtTib.StackBase: 80470650
NtTib.StackLimit: 8046d860
NtTib.SubSystemTib: 00000000
NtTib.Version: 00000000
NtTib.UserPointer: 00000000
NtTib.SelfTib: 00000000
SelfPcr: ffdff000
Prcb: ffdff120
Irql: 00000000
IRR: 00000000
IDR: ffffffff
InterruptMode: 00000000
IDT: 80036400
GDT: 80036000
TSS: 80257000
CurrentThread: 8046c610
NextThread: 00000000
IdleThread: 8046c610
DpcQueue:
No entanto, os resultados para o Processador 1 são bem diferentes. Nesse caso, o valor de NtTib.ExceptionList é f0823cc0, não 0xFFFFFFFF, indicando que esse é o processador no qual a exceção ocorreu.
0: kd> ~1
1: kd> !pcr
PCR Processor 1 @81497000
NtTib.ExceptionList: f0823cc0
NtTib.StackBase: f0823df0
NtTib.StackLimit: f0821000
NtTib.SubSystemTib: 00000000
NtTib.Version: 00000000
NtTib.UserPointer: 00000000
NtTib.SelfTib: 00000000
SelfPcr: 81497000
Prcb: 81497120
Irql: 00000000
IRR: 00000000
IDR: ffffffff
InterruptMode: 00000000
IDT: 8149b0e8
GDT: 8149b908
TSS: 81498000
CurrentThread: 81496d28
NextThread: 00000000
IdleThread: 81496d28
DpcQueue:
Quando você está no contexto correto do processador, a extensão !process exibe o processo em execução no momento.
As partes mais interessantes do despejo de processo são:
Os tempos (um valor alto indica que o processo pode ser o culpado).
A contagem de identificadores (este é o número entre parênteses após ObjectTable na primeira entrada).
O status do thread (muitos processos têm vários threads). Se o processo atual estiver ocioso, é provável que a máquina esteja realmente ociosa ou travada devido a algum problema incomum.
Embora usar a extensão !process 0 7 seja a melhor maneira de encontrar o problema em um sistema travado, às vezes é muita informação para filtrar. Em vez disso, use um !process 0 0 e, em seguida, um !process no identificador do processo para CSRSS e quaisquer outros processos suspeitos.
Ao usar um !process 0 7, muitos dos threads podem ser marcados como "pilha de kernel não residente" porque essas pilhas são paginadas. Se essas páginas ainda estiverem no cache que está em transição, você poderá obter mais informações usando um .cache decodeptes antes de !process 0 7:
kd> .cache decodeptes
kd> !process 0 7
Se você puder identificar o processo com falha, use !process <process> 7 para mostrar as pilhas de kernel para cada thread no processo. Essa saída pode identificar o problema no modo kernel e revelar o que o processo suspeito está chamando.
Além de !process, as seguintes extensões podem ajudar a determinar a causa de um computador que não responde:
Extensão | Efeito |
---|---|
Identifica os threads que estão prontos para serem executados, em ordem de prioridade. |
|
Identifica todos os bloqueios de recursos retidos, caso haja um deadlock com tempos limite de varejo. |
|
Verifica o uso da memória virtual. |
|
Determina se um tipo de alocação de pool é desproporcionalmente grande (marcação de pool necessária). |
|
Verifica o status da memória física. |
|
Verifica a validade do heap. |
|
Pesquisa o pool não paginado em busca de IRPs ativos. |
Se as informações fornecidas não indicarem uma condição incomum, tente definir um ponto de interrupção em ntoskrnl! KiSwapThread para determinar se o processador está preso em um processo ou se ainda está agendando outros processos. Se ele não estiver travado, defina pontos de interrupção em funções comuns, como NtReadFile, para determinar se o computador está preso em um caminho de código específico.