windbg 边学边记attach 进程和open dump的两个方式查看线程的占用cpu资源

时间:2023-03-08 20:45:54
windbg  边学边记attach 进程和open dump的两个方式查看线程的占用cpu资源

首先我是attach到进程的方式,附加到进程把. vs里边有个远程调试就是通过连接到远程机附加到进程操作的.在 有公网IP情况下挺好用,但涉及到nat穿越之类的,因为用户的不方便设置,这种调试方式也有局限性.

windbg  边学边记attach 进程和open dump的两个方式查看线程的占用cpu资源

6、 lmf

列出当前进程中加载的所有dll文件和对应的路径

windbg  边学边记attach 进程和open dump的两个方式查看线程的占用cpu资源

奇怪没找到我程序里边加载的dll  乖乖滴.难道attach 进程把dll关了吗? 用空用dump 试试.

11!runaway 可以显示每一个线程的cpu消耗

这个命令挺好,直接找到哪个线程占得时间久 ,如果一直占着,那这个线程里边一定是有死循环,或者不停的操作某个东西

windbg  边学边记attach 进程和open dump的两个方式查看线程的占用cpu资源

线程6号 占用时间1分钟31秒

我看有人通过抓dump  才查看,那种应该是最准的吧, windbg  附加到进程里之后,程序卡掉了,占资源的dll 也停下来了.    总结下文的操作,发现加载到进程跟dump 的方式竟然一样,不一样的估计是加载到进程里增大资源影响程序的运行效果的公正性吧.但差距不大吧.

通过dump多抓几次,每次都一样占时间的那个线程就是问题所在的线程.

12、 ~     命令是用来切换目标线程

0:018> ~ 可以显示线程的信息
0:018> ~0s   把当前的线程切换到0号线程,也就是主线程,切换后提示符会变为0:000.

13 、~* 命令列出当前进程中的所有线程的详细信息

14、~*kb    命令列出所有线程的堆栈

15、 k     命令用来显示当前线程的堆栈,如下

转到六号线程

windbg  边学边记attach 进程和open dump的两个方式查看线程的占用cpu资源

没有多少信息 这是0:007> !clrstack转到这个线程  没有列出线程的占用资源情况

应该继续下边的命令

!clrstack 
15、 k     命令用来显示当前线程的堆栈,如下

0:018> k
跟d命令一样,k后面也可以跟很多后缀,比如kb kp,kn,kv,kl等,这些后缀控制了显示的格式和信息。
栈指令k[b|p|P|v]
这四条指令显示的内容类似,但是每个指令都有特色;

KB显示三个参数;

Kp显示所有的参数,但需要Full Symbols或Private PDBSymbols支持。KP与Kp相似,只是KP将参数换行显示了;

Kv用于显示FPO和调用约定;

KD,用于显示Stack的Dump,在跟踪栈时比较有用。
这些指令区分大小。

16 、u   命令把指定地址上的代码翻译成汇编输出

0:018> u 7739d023 
USER32!NtUserWaitMessage:
7739d023 b84a120000 mov eax,0x124a
7739d028 ba0003fe7f mov edx,0x7ffe0300
7739d02d ff12 call dword ptr [edx]
7739d02f c3 ret
如果符号文件加载正确,可以用uf命令直接反汇编整个函数,比如uf USER32! NtUserWaitMessage

通过抓dump的方式

windbg  边学边记attach 进程和open dump的两个方式查看线程的占用cpu资源

0:000> !runaway
User Mode Time
Thread Time
7:1dec 0 days 0:00:37.578
0:1278 0 days 0:00:00.078
8:1274 0 days 0:00:00.015
6:2248 0 days 0:00:00.015
17:1378 0 days 0:00:00.000
16:1ff0 0 days 0:00:00.000
15:3a4 0 days 0:00:00.000
14:1e88 0 days 0:00:00.000
13:1dc4 0 days 0:00:00.000
12:ec4 0 days 0:00:00.000
11:1b98 0 days 0:00:00.000
10:2074 0 days 0:00:00.000
9:9f4 0 days 0:00:00.000
5:154c 0 days 0:00:00.000
4:1bd4 0 days 0:00:00.000
3:8ac 0 days 0:00:00.000
2:48c 0 days 0:00:00.000
1:75c 0 days 0:00:00.000

0:000> ~7s
ntdll!NtWaitForSingleObject+0xa:
00007ffd`284f386a c3 ret

 调整到7号线程上下文 

0:007> !clrstack
No export clrstack found

看来我是.net 环境没load 正确的sos 吧

windbg  边学边记attach 进程和open dump的两个方式查看线程的占用cpu资源

想通过加载sos.dll 出现下边错误 .

0:007> .load C:/WINDOWS/Microsoft.NET/Framework/v4.0.30319/sos.dll
The call to LoadLibrary(C:/WINDOWS/Microsoft.NET/Framework/v4.0.30319/sos.dll) failed, Win32 error 0n193
"%1 不是有效的 Win32 应用程序。"
Please check your debugger configuration and/or network access.

  问题一:WinDBG分X86和X64两个版本

  如果你用的是32位的WinDBG,那直接打开就行;你如果用的是64位的版本,那么如果调试64位代码也直接打开,如果调试x86的代码,要使用Wow64下的WinDBG.exe。

  问题二:确定SOS和CLR的位置和版本

  如果安装了Visual Studio的机器,可以打开VS的命令行,输入where sos.dll命令,可以找到sos.dll的全路径(需要说明的是,找到的不一定是全部的文件)。它的一般位置在C:\Windows\Microsoft.NET\Framework?\version?\SOS.dll。其中Framework?包括Framework和Framework64两个版本;version?包括v2.0.50727,v3.,v3.5和v4..30319等版本。文件确切路径的选择依据要调试程序的版本而定,一般为C:\Windows\Microsoft.NET\Framework\v4.0.30319\SOS.dll,CLR为同一目录下的CLR.dll文件。

  问题三:加载SOS和CLR

  运气好的话,使用命令.load C:\Windows\Microsoft.NET\Framework\v4.0.30319\SOS.dll可以加载成功。如果失败,特别是出现The call to LoadLibrary(C:\Windows\Microsoft.NET\Framework\v4.0.30319\sos.dll) failed, Win32 error 0n193这样的错误,请确认加载sos.dll的版本是否正确。

  此外,加载不出错,并不见得可以直接使用。可以尝试命令.loadby sos clr。如果命令成功,那么测试环境好了。如果出现了“Unable to find module 'clr'”这样的错误。请键入g让调试程序运行一会儿,停下来的时候再尝试命令.loadby sos clr,这时一般都会成功。

C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC>where sos.dll
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\SOS.dll

0:007> .load C:\Windows\Microsoft.NET\Framework64\v4.0.30319\SOS.dll

什么提示也没有,看来是正确了吗

继续上边的

0:007> ~7s
ntdll!NtWaitForSingleObject+0xa:
00007ffd`284f386a c3 ret

终于成功:

:> !clrstack
OS Thread Id: 0x1dec ()
Child SP IP Call Site
000000001d05f1c8 00007ffd284f386a [InlinedCallFrame: 000000001d05f1c8] Cognex.DataMan.LegacyUtils.PInvoke.WaitForSingleObject(IntPtr, UInt32)
000000001d05f1c8 00007ffca7bb59dc [InlinedCallFrame: 000000001d05f1c8] Cognex.DataMan.LegacyUtils.PInvoke.WaitForSingleObject(IntPtr, UInt32)
000000001d05f1a0 00007ffca7bb59dc DomainBoundILStubClass.IL_STUB_PInvoke(IntPtr, UInt32)
000000001d05f250 00007ffca7bb5909 Cognex.DataMan.LegacyUtils.PInvoke.WaitOne(IntPtr, UInt32)
000000001d05f280 00007ffca7bb580c Cognex.DataMan.LegacyUtils.BlockingCollection`[[System.__Canon, mscorlib]].DequeueWithCancellation(Cognex.DataMan.LegacyUtils.CancellationToken)
000000001d05f2d0 00007ffca7bb5544 Cognex.DataMan.CogNamer.CogNamerListener.CogNamerDispatcherThreadFunc(System.Object)
000000001d05f320 00007ffcfcacaffe System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
000000001d05f3f0 00007ffcfcacae97 System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
000000001d05f420 00007ffcfcacae52 System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object)
000000001d05f470 00007ffcfca1c142 System.Threading.ThreadHelper.ThreadStart()
000000001d05f6c8 00007ffd07213cd3 [GCFrame: 000000001d05f6c8]
000000001d05fa18 00007ffd07213cd3 [DebuggerU2MCatchHandlerFrame: 000000001d05fa18]

接触了几天了,今天终于是操作了一个流程下来,能看到这个线程的托管代码了

000000001d05f1c8 00007ffd284f386a [InlinedCallFrame: 000000001d05f1c8] Cognex.DataMan.LegacyUtils.PInvoke.WaitForSingleObject(IntPtr, UInt32)
000000001d05f1c8 00007ffca7bb59dc [InlinedCallFrame: 000000001d05f1c8] Cognex.DataMan.LegacyUtils.PInvoke.WaitForSingleObject(IntPtr, UInt32)
000000001d05f1a0 00007ffca7bb59dc DomainBoundILStubClass.IL_STUB_PInvoke(IntPtr, UInt32)

也列出了其中占资源大的托管代码

参考

http://www.360doc.com/content/12/0524/13/8053702_213354653.shtml