检查dump文件的时候, 我们经常会使用下面的命令来获得所有线程上的调用栈

~*e !clrstack

输出结果举例如下:

OS Thread Id: 0x1b30 (15)
Child-SP         RetAddr          Call Site
0000000034a9ed00 000006424e611fc0 System.Threading.WaitHandle.WaitOne(Int64, Boolean)
0000000034a9ed40 00000642782f174b System.DirectoryServices.Protocols.PartialResultsRetriever.ThreadRoutine()
0000000034a9ed90 000006427838956d System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object)
0000000034a9ede0 000006427f602322 System.Threading.ThreadHelper.ThreadStart()
OS Thread Id: 0x10fc (16)
Unable to walk the managed stack. The current thread is likely not a
managed thread. You can run !threads to get a list of managed threads in
the process
OS Thread Id: 0x26f8 (17)
Child-SP         RetAddr          Call Site
00000000431bf060 0000064274a56477 System.Threading.WaitHandle.WaitAny(System.Threading.WaitHandle[], Int32, Boolean)
00000000431bf0c0 00000642782f174b System.Net.TimerThread.ThreadProc()
00000000431bf190 000006427838956d System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object)
00000000431bf1e0 000006427f602322 System.Threading.ThreadHelper.ThreadStart()

在这个结果输出里, 可以很轻易地看出线程号15, 16, 17.

然而, 当检查非托管调用栈的时候, 这个线程号却很难看到. 命令:

~*e k

输出片段如下:

Child-SP          RetAddr           Call Site
00000000`34f1f6d8 00000000`77efb416 ntdll!ZwWaitForSingleObject+0xa [d:\nt\base\…\usrstubs.asm @ 180]
00000000`34f1f6e0 00000000`77efb480 ntdll!RtlpWaitOnCriticalSection+0x240 [d:\nt\….c @ 617]
00000000`34f1f760 00000000`35f7da11 ntdll!RtlEnterCriticalSection+0xa9 [d:\nt\…\resource.c @ 876]
00000000`34f1f790 00000000`35f7dc8b ONETUTIL!COWSHeap::RunLeakDetectionInternal+0x281
00000000`34f1f7e0 00000000`35f7e081 ONETUTIL!COWSMemmgr::AcquireLocalHeap+0x13
00000000`34f1f820 00000000`3561c500 ONETUTIL!COWSMemmgr::InitMemmgrForThread+0x4d
00000000`34f1f880 00000000`3000670d OWSSVR!GetExtensionVersion+0x5b14
00000000`34f1f900 00000000`35febb0d OWSTIMER!VTimerProcessRequest+0xa1 [d:\….cpp @ 225]
00000000`34f1fc30 00000000`35fece4e ONETUTIL!COWSThreadWithHeap::WalkHeap+0x1fd
00000000`34f1fc80 00000000`781337d7 ONETUTIL!COWSThreadWithHeap::Uninitialize+0x97e
00000000`34f1ff20 00000000`78133894 msvcr80!_callthreadstartex+0x17 [f:\dd\vctools\crt_…\crt\src\threadex.c @ 348]
00000000`34f1ff50 00000000`77d6b71a msvcr80!_threadstartex+0x84 [f:\dd\vctools…\crt\src\threadex.c @ 326]
00000000`34f1ff80 00000000`00000000 kernel32!BaseThreadStart+0x3a [d:\nt\…\support.c @ 795]
Child-SP          RetAddr           Call Site
00000000`35c1f6d8 00000000`77efb416 ntdll!ZwWaitForSingleObject+0xa [d:\nt\base\…\usrstubs.asm @ 180]
00000000`35c1f6e0 00000000`77efb480 ntdll!RtlpWaitOnCriticalSection+0x240 [d:\nt\….c @ 617]
00000000`35c1f760 00000000`35f7da11 ntdll!RtlEnterCriticalSection+0xa9 [d:\nt\base….c @ 876]
00000000`35c1f790 00000000`35f7dc8b ONETUTIL!COWSHeap::RunLeakDetectionInternal+0x281
00000000`35c1f7e0 00000000`35f7e081 ONETUTIL!COWSMemmgr::AcquireLocalHeap+0x13
00000000`35c1f820 00000000`3561c500 ONETUTIL!COWSMemmgr::InitMemmgrForThread+0x4d
00000000`35c1f880 00000000`3000670d OWSSVR!GetExtensionVersion+0x5b14
00000000`35c1f900 00000000`35febb0d OWSTIMER!VTimerProcessRequest+0xa1 [d:\….cpp @ 225]
00000000`35c1fc30 00000000`35fece4e ONETUTIL!COWSThreadWithHeap::WalkHeap+0x1fd
00000000`35c1fc80 00000000`781337d7 ONETUTIL!COWSThreadWithHeap::Uninitialize+0x97e
00000000`35c1ff20 00000000`78133894 msvcr80!_callthreadstartex+0x17 [f:\dd…\crt…threadex.c @ 348]
00000000`35c1ff50 00000000`77d6b71a msvcr80!_threadstartex+0x84 [f:\dd\…\crt\src\t…adex.c @ 326]
00000000`35c1ff80 00000000`00000000 kernel32!BaseThreadStart+0x3a [d:\…base\…support.c @ 795]

那么如何才能得到这个这两个调用栈的线程号码呢?

答案的命令如下:

~*e !teb;k

这个命令的意思是遍历所有的线程, 先输出线程的TEB(Thread Environment Block)数据结构, 再输出调用栈.

根据Mark E. Russinvoich的Windows Internals 5th Edition的P378页的讲解, TEB结构中是存有Thread ID这个信息的, 位置在Active RPC handle的正上方. 书中截图如下:

让我们检查一下在我们的WinDBG中的输出结果吧.

TEB at 000007ffffe66000
    ExceptionList:        0000000000000000
    StackBase:            0000000034f20000
    StackLimit:           0000000034f1c000
    SubSystemTib:         0000000000000000
    FiberData:            0000000000001e00
    ArbitraryUserPointer: 0000000000000000
    Self:                 000007ffffe66000
    EnvironmentPointer:   0000000000000000
    ClientId:             0000000000000490 . 00000000000023e8
    RpcHandle:            0000000000000000
    Tls Storage:          0000000000000000
    PEB Address:          000007fffffde000
    LastErrorValue:       0
    LastStatusValue:      c0150008
    Count Owned Locks:    0
    HardErrorMode:        0
Child-SP          RetAddr           Call Site
00000000`34f1f6d8 00000000`77efb416 ntdll!ZwWaitForSingleObject+0xa [d:\nt\….asm @ 180]
00000000`34f1f6e0 00000000`77efb480 ntdll!RtlpWaitOnCriticalSection+0x240 [d:\nt\base….c @ 617]
00000000`34f1f760 00000000`35f7da11 ntdll!RtlEnterCriticalSection+0xa9 [d:\nt\base\….c @ 876]
00000000`34f1f790 00000000`35f7dc8b ONETUTIL!COWSHeap::RunLeakDetectionInternal+0x281
00000000`34f1f7e0 00000000`35f7e081 ONETUTIL!COWSMemmgr::AcquireLocalHeap+0x13
00000000`34f1f820 00000000`3561c500 ONETUTIL!COWSMemmgr::InitMemmgrForThread+0x4d
00000000`34f1f880 00000000`3000670d OWSSVR!GetExtensionVersion+0x5b14
00000000`34f1f900 00000000`35febb0d OWSTIMER!VTimerProcessRequest+0xa1 [d:\….cpp @ 225]
00000000`34f1fc30 00000000`35fece4e ONETUTIL!COWSThreadWithHeap::WalkHeap+0x1fd
00000000`34f1fc80 00000000`781337d7 ONETUTIL!COWSThreadWithHeap::Uninitialize+0x97e
00000000`34f1ff20 00000000`78133894 msvcr80!_callthreadstartex+0x17 [f:\dd\….c @ 348]
00000000`34f1ff50 00000000`77d6b71a msvcr80!_threadstartex+0x84 [f:\dd\…\crt\src….c @ 326]
00000000`34f1ff80 00000000`00000000 kernel32!BaseThreadStart+0x3a [d:\nt\base\……c @ 795]
TEB at 000007ffffe64000
    ExceptionList:        0000000000000000
    StackBase:            0000000035c20000
    StackLimit:           0000000035c1c000
    SubSystemTib:         0000000000000000
    FiberData:            0000000000001e00
    ArbitraryUserPointer: 0000000000000000
    Self:                 000007ffffe64000
    EnvironmentPointer:   0000000000000000
    ClientId:             0000000000000490 . 000000000000107c
    RpcHandle:            0000000000000000
    Tls Storage:          0000000000000000
    PEB Address:          000007fffffde000
    LastErrorValue:       0
    LastStatusValue:      c0150008
    Count Owned Locks:    0
    HardErrorMode:        0
Child-SP          RetAddr           Call Site
00000000`35c1f6d8 00000000`77efb416 ntdll!ZwWaitForSingleObject+0xa [d:\….asm @ 180]
00000000`35c1f6e0 00000000`77efb480 ntdll!RtlpWaitOnCriticalSection+0x240 [d:\nt\…\reso….c @ 617]
00000000`35c1f760 00000000`35f7da11 ntdll!RtlEnterCriticalSection+0xa9 [d:\nt\…\ntdll\…rce.c @ 876]
00000000`35c1f790 00000000`35f7dc8b ONETUTIL!COWSHeap::RunLeakDetectionInternal+0x281
00000000`35c1f7e0 00000000`35f7e081 ONETUTIL!COWSMemmgr::AcquireLocalHeap+0x13
00000000`35c1f820 00000000`3561c500 ONETUTIL!COWSMemmgr::InitMemmgrForThread+0x4d
00000000`35c1f880 00000000`3000670d OWSSVR!GetExtensionVersion+0x5b14
00000000`35c1f900 00000000`35febb0d OWSTIMER!VTimerProcessRequest+0xa1 [d:\…\timerecb…@ 225]
00000000`35c1fc30 00000000`35fece4e ONETUTIL!COWSThreadWithHeap::WalkHeap+0x1fd
00000000`35c1fc80 00000000`781337d7 ONETUTIL!COWSThreadWithHeap::Uninitialize+0x97e
00000000`35c1ff20 00000000`78133894 msvcr80!_callthreadstartex+0x17 [f:\dd\vctools\…\crt\src\t…ex.c @ 348]
00000000`35c1ff50 00000000`77d6b71a msvcr80!_threadstartex+0x84 [f:\dd\vctools\crt_bld\…\crt\src\threadex.c @ 326]
00000000`35c1ff80 00000000`00000000 kernel32!BaseThreadStart+0x3a [d:\nt\…\…c @ 795]

这里的ClientId就应该是线程号了, 长得很奇怪是么? 呵呵, 让我们来找到它们的数字号码吧.

0000000000000490 . 00000000000023e8 = 490.23e8

0000000000000490 . 000000000000107c = 490.107c

输入命令

0:039> ~
   0  Id: 490.16ec Suspend: 1 Teb: 000007ff`fffdc000 Unfrozen
   1  Id: 490.1884 Suspend: 1 Teb: 000007ff`fffd8000 Unfrozen
   2  Id: 490.1200 Suspend: 1 Teb: 000007ff`fffa2000 Unfrozen
   3  Id: 490.a10 Suspend: 1 Teb: 000007ff`fff9e000 Unfrozen
…………
  26  Id: 490.1c4c Suspend: 1 Teb: 000007ff`ffe90000 Unfrozen
  27  Id: 490.1b88 Suspend: 1 Teb: 000007ff`ffe86000 Unfrozen
  28  Id: 490.290c Suspend: 1 Teb: 000007ff`ffe72000 Unfrozen
…………

34  Id: 490.2b64 Suspend: 1 Teb: 000007ff`ffeec000 Unfrozen
  35  Id: 490.2360 Suspend: 1 Teb: 000007ff`ffed8000 Unfrozen
  36  Id: 490.a2c Suspend: 1 Teb: 000007ff`fffd6000 Unfrozen
  …………

62  Id: 490.2b04 Suspend: 0 Teb: 000007ff`ffebc000 Unfrozen
  63  Id: 490.2004 Suspend: 1 Teb: 000007ff`ffeba000 Unfrozen
  64  Id: 490.24a8 Suspend: 0 Teb: 000007ff`ffeb8000 Unfrozen
…………

72  Id: 490.9bc Suspend: 1 Teb: 000007ff`ffea6000 Unfrozen
  73  Id: 490.2494 Suspend: 1 Teb: 000007ff`ffea4000 Unfrozen
  74  Id: 490.2724 Suspend: 1 Teb: 000007ff`ffea2000 Unfrozen
…………
  92  Id: 490.29c8 Suspend: 1 Teb: 000007ff`ffe78000 Unfrozen
  93  Id: 490.1da8 Suspend: 1 Teb: 000007ff`ffe76000 Unfrozen
…………

98  Id: 490.2650 Suspend: 1 Teb: 000007ff`ffe6a000 Unfrozen
  99  Id: 490.23e8 Suspend: 1 Teb: 000007ff`ffe66000 Unfrozen
 100  Id: 490.107c Suspend: 1 Teb: 000007ff`ffe64000 Unfrozen
101  Id: 490.1b98 Suspend: 1 Teb: 000007ff`ffe62000 Unfrozen
102  Id: 490.2bd4 Suspend: 1 Teb: 000007ff`ffe60000 Unfrozen
……………

108  Id: 490.a5c Suspend: 0 Teb: 000007ff`ffe4e000 Unfrozen
109  Id: 490.980 Suspend: 1 Teb: 000007ff`ffe4a000 Unfrozen

我们终于找到了, 线程号码为99和100.

验证一下吧

0:099> ~99s;k
ntdll!ZwWaitForSingleObject+0xa:
00000000`77ef047a c3              ret
Child-SP          RetAddr           Call Site
00000000`34f1f6d8 00000000`77efb416 ntdll!ZwWaitForSingleObject+0xa [d:…asm @ 180]
00000000`34f1f6e0 00000000`77efb480 ntdll!RtlpWaitOnCriticalSection+0x240 [d:….c @ 617]
00000000`34f1f760 00000000`35f7da11 ntdll!RtlEnterCriticalSection+0xa9 [d:\nt\….c @ 876]
00000000`34f1f790 00000000`35f7dc8b ONETUTIL!COWSHeap::RunLeakDetectionInternal+0x281
00000000`34f1f7e0 00000000`35f7e081 ONETUTIL!COWSMemmgr::AcquireLocalHeap+0x13
00000000`34f1f820 00000000`3561c500 ONETUTIL!COWSMemmgr::InitMemmgrForThread+0x4d
00000000`34f1f880 00000000`3000670d OWSSVR!GetExtensionVersion+0x5b14
00000000`34f1f900 00000000`35febb0d OWSTIMER!VTimerProcessRequest+0xa1 [d:…@ 225]
00000000`34f1fc30 00000000`35fece4e ONETUTIL!COWSThreadWithHeap::WalkHeap+0x1fd
00000000`34f1fc80 00000000`781337d7 ONETUTIL!COWSThreadWithHeap::Uninitialize+0x97e
00000000`34f1ff20 00000000`78133894 msvcr80!_callthreadstartex+0x17 [f:\…\…@ 348]
00000000`34f1ff50 00000000`77d6b71a msvcr80!_threadstartex+0x84 [f:\dd….c @ 326]
00000000`34f1ff80 00000000`00000000 kernel32!BaseThreadStart+0x3a [d:\….c @ 795]

[技巧]如何获得某个callstack所在线程的线程号?相关推荐

  1. java线程池游戏代码,Java游戏起步:(一)线程与线程池-JSP教程,Java技巧及代码...

    任何游戏都至少需要运行两个线程,主线程和gui线程 而线程池是一个管理运行线程的有用工具,下面的代码示范了一个线程池的实现方法~~ ********************************** ...

  2. C#中的线程(二) 线程同步基础

    1.同步要领 下面的表格列展了.NET对协调或同步线程动作的可用的工具:                       简易阻止方法 构成 目的 Sleep 阻止给定的时间周期 Join 等待另一个线程 ...

  3. C#多线程编程(1)--线程,线程池和Task

    C#多线程编程(1)--线程,线程池和Task 新开了一个多线程编程系列,该系列主要讲解C#中的多线程编程.    利用多线程的目的有2个: 一是防止UI线程被耗时的程序占用,导致界面卡顿:二是能够利 ...

  4. linux 线程--内核线程、用户线程实现方法

    Linux上进程分3种,内核线程(或者叫核心进程).用户进程.用户线程 内核线程拥有 进程描述符.PID.进程正文段.核心堆栈 当和用户进程拥有相同的static_prio 时,内核线程有机会得到更多 ...

  5. Java Review - 创建线程和线程池时建议指定与业务相关的名称

    文章目录 概述 线程 不指定线程名称为何难定位问题 Thread默认的线程名称 指定线程名称 线程池 不指定线程池名称为何难定位问题 指定线程名称 自定义线程名称 小结 概述 在日常开发中,当在一个应 ...

  6. java 线程 操作系统线程_线程基础:线程(1)——操作系统和线程原理

    1.概述 我在写"系统间通信技术专栏"的时候,收到很多读者的反馈.其中有一部分读者希望我抽空写一写自己关于对Java线程的使用经验和总结.巧的是,这个月我所在的技术团队也有很多同事 ...

  7. java线程组 线程池_JAVA多线程(三)-----线程组、线程池和线程相关类

    一.线程组和未处理的异常 Thread类提供了如下几个构造器来设置新创建的线程属于哪个线程组: Thread(ThreadGroup group,Runnable target):以target的ru ...

  8. java 重启线程_java 可重启线程及线程池类的设计(详解)

    了解JAVA多线程编程的人都知道,要产生一个线程有两种方法,一是类直接继承Thread类并实现其run()方法:二是类实现Runnable接口并实现其run()方法,然后新建一个以该类为构造方法参数的 ...

  9. main线程 子线程 顺序_面试官:线程池如何按照core、max、queue的执行顺序去执行?详解...

    前言 这是一个真实的面试题. 前几天一个朋友在群里分享了他刚刚面试候选者时问的问题:"线程池如何按照core.max.queue的执行循序去执行?". 我们都知道线程池中代码执行顺 ...

最新文章

  1. sql server数据库定时自动备份
  2. dex文件结构(二):dex文件加载基本原理
  3. 宝塔控制面板创建ftp后链接不上的解决方法
  4. Oracle Study之--Oracle等待事件(2)
  5. Kali 2.0 采用ssh连接登陆
  6. java同步方法的特点_java多线程有哪些优点?同步实例代码展示
  7. 利用C#实现分布式数据库查询
  8. Spark在文本统计中的简单应用
  9. 一、TensorFlow的简介和安装和一些基本概念
  10. Java是如何读到hbase-site.xml 的内容的
  11. excel文件损坏修复绝招_电脑常识:电脑提示dll文件丢失/损坏,该怎么修复?...
  12. Amobea读写分离
  13. 乐鑫再次称王WiFi MCU市场
  14. 出租车计费器的Verilog语言简单完成
  15. m序列自相关matlab代码,m序列的输出及其自相关序列
  16. python输出9*9口诀表_python 9*9 乘法表
  17. 平面设计文字排版方式有哪些?设计师们收藏——黎乙丙
  18. 47名应届生毕业生,骗领49万杭州人才补贴!检察机关建议从宽处理
  19. EXCEPTION_ACCESS_VIOLATION异常
  20. 考研英语 词根词缀单词71-80

热门文章

  1. zookeeper+kafka集群部署+storm集群
  2. 我的WCF之旅(6):在Winform Application中调用Duplex Service出现TimeoutException的原因和解决方案...
  3. asp.net在线人数限制
  4. 《Hadoop集群与安全》一2.1 在Hadoop集群中配置操作系统
  5. Oracle按照时间统计总结
  6. 【干货分享】流程DEMO-人员调动流程
  7. jquery-1.11.3.js与jquery-1.11.3.min.js区别
  8. Apache Libcloud 0.12.3 发布
  9. javascript 检测 header下载文件--插件
  10. 区块链用AI和大数据改变行业现状