Windbg命令学习6(!runaway和~)
1.!runaway
!runaway命令显示每个线程消费的时间
- Bit 0 (0x1) 让调试器显示每个线程消耗的用户模式时间(user time),默认不加就是0x1
- Bit 1 (0x2) 显示每个线程消耗的内核时间(kernel time)。
- Bit 2 (0x4) 显示每个线程从创建开始经历了多少时间。
- 就是三者的组合:1 2 3 4 5 6 7
- 0:002> !runaway User Mode Time Thread Time 0:890 0 days 0:00:00.031 2:a00 0 days 0:00:00.000 1:1174 0 days 0:00:00.000 0:002> !runaway 1 User Mode Time Thread Time 0:890 0 days 0:00:00.031 2:a00 0 days 0:00:00.000 1:1174 0 days 0:00:00.000 0:002> !runaway 2 Kernel Mode Time Thread Time 0:890 0 days 0:00:00.062 2:a00 0 days 0:00:00.000 1:1174 0 days 0:00:00.000 0:002> !runaway 3 User Mode Time Thread Time 0:890 0 days 0:00:00.031 2:a00 0 days 0:00:00.000 1:1174 0 days 0:00:00.000 Kernel Mode Time Thread Time 0:890 0 days 0:00:00.062 2:a00 0 days 0:00:00.000 1:1174 0 days 0:00:00.000 0:002> !runaway 4 Elapsed Time Thread Time 0:890 0 days 0:38:34.825 1:1174 0 days 0:38:34.793 2:a00 0 days 0:38:24.528 0:002> !runaway 7 User Mode Time Thread Time 0:890 0 days 0:00:00.031 2:a00 0 days 0:00:00.000 1:1174 0 days 0:00:00.000 Kernel Mode Time Thread Time 0:890 0 days 0:00:00.062 2:a00 0 days 0:00:00.000 1:1174 0 days 0:00:00.000 Elapsed Time Thread Time 0:890 0 days 0:38:41.825 1:1174 0 days 0:38:41.793 2:a00 0 days 0:38:31.528 - 该扩展命令可以用来快速找出哪些线程循环失去控制消耗了太多CPU时间。输出中以调试器的内部线程号和16进制线程ID来标识每个线程。还会显示调试器ID,当然,主要用于分析dump文件 
- 
2 ~ 波形符(~) 命令显示指定线程或当前进程中的所有线程的信息 
 这条命令显示所有线程
- 
0:001> ~ 
- 
该命令也显示所有线程。 0:001> ~* 
- 
下面的命令显示当前活动线程。 0:001> ~. 
- 
下面的命令显示原始的产生异常的线程(或调试器附加到进程时活动的线程)。 0:001> ~# 
- 
下面显示号码为2的线程。 0:001> ~2 
- 
0:002> ~ 0 Id: 17a4.eb4 Suspend: 1 Teb: 7ffdf000 Unfrozen 1 Id: 17a4.d4c Suspend: 1 Teb: 7ffde000 Unfrozen . 2 Id: 17a4.aac Suspend: 1 Teb: 7ffdd000 Unfrozen 0:002> ~* 0 Id: 17a4.eb4 Suspend: 1 Teb: 7ffdf000 Unfrozen Start: calc!WinMainCRTStartup (01012475) Priority: 0 Priority class: 32 Affinity: f 1 Id: 17a4.d4c Suspend: 1 Teb: 7ffde000 Unfrozen Start: winimhc!TGetLogConfig+0x507b (10012f7b) Priority: 0 Priority class: 32 Affinity: f . 2 Id: 17a4.aac Suspend: 1 Teb: 7ffdd000 Unfrozen Priority: 0 Priority class: 32 Affinity: f 0:002> ~0 0 Id: 17a4.eb4 Suspend: 1 Teb: 7ffdf000 Unfrozen Start: calc!WinMainCRTStartup (01012475) Priority: 0 Priority class: 32 Affinity: f 0:002> ~# . 2 Id: 17a4.aac Suspend: 1 Teb: 7ffdd000 Unfrozen Priority: 0 Priority class: 32 Affinity: f我们可以发现,~和~*还是有点区别的,~*会把入口函数和优先级都打印出来, 
- 0 Id: 17a4.eb4 Suspend: 1 Teb: 7ffdf000 Unfrozen意思是0号线程,进程ID为17a4,线程ID为eb4,暂停数为1,未冻结状态 
- ,每个线程都包含了一个暂停计数(Suspend Count),以及一个冻结/解冻(Frozen/Unfrozen)的状态。 
 
 暂停计数由Windows内核使用的值,可以通过SuspendThread和ResumeThread这两个系统函数来控制的,核心编程里说一个线程创建时,暂停次数为1,
- 当线程完全初始化后,系统就要查看CREATE_SUSPEND标志是否已经传递给CreateThread。如果该标志没有传递,系统便将线程的暂停计数递减为0, 
- 该线程可以调度到一个进程中 
- 也可以用~<tid>n增加暂停计数,用~<tid>m减少暂停计数,如下: 
- 0:002> ~0n 0:002> ~ 0 Id: 17a4.eb4 Suspend: 2 Teb: 7ffdf000 Unfrozen 1 Id: 17a4.d4c Suspend: 1 Teb: 7ffde000 Unfrozen . 2 Id: 17a4.aac Suspend: 1 Teb: 7ffdd000 Unfrozen 0:002> ~0m 0:002> ~ 0 Id: 17a4.eb4 Suspend: 1 Teb: 7ffdf000 Unfrozen 1 Id: 17a4.d4c Suspend: 1 Teb: 7ffde000 Unfrozen . 2 Id: 17a4.aac Suspend: 1 Teb: 7ffdd000 Unfrozen 0:002> ~0m 0:002> ~ 0 Id: 17a4.eb4 Suspend: 0 Teb: 7ffdf000 Unfrozen 1 Id: 17a4.d4c Suspend: 1 Teb: 7ffde000 Unfrozen . 2 Id: 17a4.aac Suspend: 1 Teb: 7ffdd000 Unfrozen 0:002> ~1m 0:002> ~ 0 Id: 17a4.eb4 Suspend: 0 Teb: 7ffdf000 Unfrozen 1 Id: 17a4.d4c Suspend: 0 Teb: 7ffde000 Unfrozen . 2 Id: 17a4.aac Suspend: 1 Teb: 7ffdd000 Unfrozen 
 比如我只调用一次~0n,那么主线程的引用计数变为2了,我再调用g,主线程的引用计数变为1,我们的calc是运行不起来的!
- 
冻结状态是调试器的状态,在window操作系统中是不支持这个概念,对于每个被冻结的线程,调试器将记住这个状态,并且在调试事件被处理之前增加线程的挂起计数,当调试事件被处理完毕时,挂起计数将被递减,对应的命令为: 
- 
冻结~<tid>f 
- 
解冻~<tid>u 
- 
冻结命令数量必须和解冻命令数量相等 
- 
 
                     
                    
                 
                    
                 
                
            
         
 
         浙公网安备 33010602011771号
浙公网安备 33010602011771号