分享
 
 
 

用WinDbg探索CLR世界 [2] 线程

王朝system·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

http://flier_lu.blogone.net/?id=1370342

[2] 线程

在配置好WinDbg之后,我们载入一个CLR程序并执行至CLR被载入,然后开始我们的CLR探索之旅。

首先,使用!threads命令看看当前CLR中有哪些线程正在执行

以下为引用:

0:004> !threads

ThreadCount: 2

UnstartedThread: 0

BackgroundThread: 1

PendingThread: 0

DeadThread: 0

PreEmptive GC Alloc Lock

ID ThreadOBJ State GC Context Domain Count APT Exception

0 6ec 0014e708 6020 Enabled 00000000:00000000 00148a90 0 STA

2 a68 00157618 b220 Enabled 00000000:00000000 00148a90 0 MTA (Finalizer)

前面5个计数器分别表示托管(managed)线程、未启动线程、后台线程、阻塞线程和僵死线程的数量。

下面的列表是当前托管线程的详细信息:第一个域是WinDbg的线程编号;ID是Win32线程ID;ThreadObj是线程的对象;State是一个标志位,以后再详细介绍;PreEmptive GC表示GC是否与此线程协作;GC Alloc Context是GC的相关信息;Domain是线程所在AppDomain;Lock Count是线程拥有锁的计数器;APT是线程类型,沿用COM中STA/MTA/NTA(netural)的概念;最后的Exception表示线程类型,除了普通的用户线程外还有finalizer、GC、Theadpool Worker和Threadpool Completion Port,其功能与名字相符。

我们可以在.NET Framework SDK的Tool Developers Guide\Samples\sos子目录下找到所有sos.dll支持命令的详细说明;在rotor的clr\src\tools\sos子目录下找到针对rotor系统的sos.dll的实现代码。这份源代码在功能上实现了与CLR正规发行版本基本上相同的功能,也是我们下面研究的主要目标之一。

其中Strike.cpp是sos功能命令的实现所在。每个sos的命令在strike.cpp中以一个函数实现,通过DECLARE_API宏定义函数参数。

以下为引用:

#define DECLARE_API(s) CPPMOD VOID s( HANDLE hCurrentProcess, HANDLE hCurrentThread, ULONG dwCurrentPc, ULONG dwProcessor, PCSTR args )

函数参数分别传入WinDbg正在调试的进程句柄、当前线程句柄、当前指令地址、处理器和命令行参数信息。函数内再对此信息进行处理,输出调试信息到WinDbg界面中。

让我们先看看Threads命令(strike.cpp:1237)的实现原理。

Threads函数首先从一个全局线程存储池中获取当前线程统计信息,并将之存储在一个结构并内打印统计值;然后调用GetThreadList函数(sos\util.cpp:2259)获取线程列表;对每个线程获取线程信息,并将之存储在一个结构内并打印线程详细信息;在打印线程信息时,会判断此线程的类型,并打印相关信息。

首先来看看全局线程存储池ThreadStore类(vm\threads.h:1998)的设计和使用思路。

CLR在启动时,会通过 CoInitializeEE 函数(vm\ceemain.cpp:1100)初始化一个执行引擎(Execute Engine),这儿的EE类似JVM的概念,实际上就是CLR的运行时环境。关于CLR的详细启动过程请参见笔者另外一篇文章《.Net平台下CLR程序载入原理分析》

CoInitializeEE函数使用全局变量保障每个进程最多只有一个CLR环境;对没有构造CLR的进程,调用TryEEStartup函数(vm\ceemain.cpp:500)尝试初始化CLR。伪代码如下:

以下为引用:

HRESULT STDMETHODCALLTYPE CoInitializeEE(DWORD fFlags)

{

if(++g_RefCount <= 1 && !g_fEEStarted && !g_fEEInit)

{

g_EEStartupStatus = TryEEStartup(fFlags);

}

return SUCCEEDED(g_EEStartupStatus) ?

(SetupThread() ? S_OK : E_OUTOFMEMORY) : g_EEStartupStatus;

}

TryEEStartup函数则以异常安全策略包装EEStartup函数(vm\ceemain.cpp:206)完成实际的CLR启动工作。在EEStartup函数中会真正调用InitThreadManager函数(vm\Threads.cpp:2068)完成线程管理器的初始化工作。而InitThreadManager函数出了初始化TLS外,绝大部分工作是由实现ThreadStore类的Singleton模式的ThreadStore::InitThreadStore函数(vm\Threads.cpp:4345)实现的。其中保存全局唯一ThreadStore类实例的就是前面获取线程统计信息的全局线程存储池。

以下为引用:

ThreadStore *g_pThreadStore;

BOOL ThreadStore::InitThreadStore()

{

g_pThreadStore = new ThreadStore;

return (g_pThreadStore != NULL);

}

因此,ThreadStore类实际上是一个全局唯一的线程管理器,新增和终止一个CLR线程都需要在此存储中更新相关信息。此线程管理器除了维护一个当前线程列表的链表外,还维护了一套线程相关信息的统计值。前面Threads命令获取的几个统计值就是从此而来。而获取当前线程列表的GetThreadList函数(sos\util.cpp:2259),实际上也是直接从线程管理器的线程列表中获取每个线程对象的入口。

最后来看看线程信息的获取步骤。

每个线程Thread类(vm\Threads.h:544)的对象表示一个managed线程。此线程是一个逻辑上的线程,如果被启动则可能直接对应于一个系统的物理线程。而一个物理线程则无需绑定到一个被管理的逻辑线程上,物理线程却可以在多个AppDomain中共享以运行被调度到的被管理线程。此外每个被管理的线程必须有一个运行时环境(Contex),但不一定在一个确定的应用程序域(AppDomain)中。呵呵,搞糊涂了吧 :D 这里绕的几个弯子我以后再写篇详细的文章讨论好了 :P

被管理的线程除了可以获取当前线程ID和绑定到的物理线程ID外,还有一个ThreadState状态(vm\Threads.h:576)定义其当前运行情况。

对线程类型的判断逻辑,首先将线程与FinalizerThread(Finalizer)和GcThread(GC)两个全局变量指向的系统功能线程比较,判断是否是这两种特殊线程;然后根据线程状态的Thread::TS_ThreadPoolThread位是否被设置来判断是否在线程池中;如果在线程池中还要通过状态的Thread::TS_TPWorkerThread标志位进一步判断是否为工作者线程(Threadpool Worker),不是工作者线程则为完成端口线程(Threadpool Completion Port)。这几种线程缓冲池中线程的概念,我们以后章节讨论线程池时再详细讨论。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有