新书推介:《语义网技术体系》
作者:瞿裕忠,胡伟,程龚
   XML论坛     W3CHINA.ORG讨论区     计算机科学论坛     SOAChina论坛     Blog     开放翻译计划     新浪微博  
 
  • 首页
  • 登录
  • 注册
  • 软件下载
  • 资料下载
  • 核心成员
  • 帮助
  •   Add to Google

    >> 本版讨论.NET,C#,ASP,VB技术
    [返回] 中文XML论坛 - 专业的XML技术讨论区计算机技术与应用『 Dot NET,C#,ASP,VB 』 → 用WinDbg探索CLR世界 [2] 线程 查看新帖用户列表

      发表一个新主题  发表一个新投票  回复主题  (订阅本版) 您是本帖的第 5771 个阅读者浏览上一篇主题  刷新本主题   树形显示贴子 浏览下一篇主题
     * 贴子主题: 用WinDbg探索CLR世界 [2] 线程 举报  打印  推荐  IE收藏夹 
       本主题类别:     
     admin 帅哥哟,离线,有人找我吗?
      
      
      
      威望:9
      头衔:W3China站长
      等级:计算机硕士学位(管理员)
      文章:5255
      积分:18406
      门派:W3CHINA.ORG
      注册:2003/10/5

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给admin发送一个短消息 把admin加入好友 查看admin的个人资料 搜索admin在『 Dot NET,C#,ASP,VB 』的所有贴子 点击这里发送电邮给admin  访问admin的主页 引用回复这个贴子 回复这个贴子 查看admin的博客楼主
    发贴心情 用WinDbg探索CLR世界 [2] 线程


    发信人: flier (小海 [寻找风车中]), 信区: DotNET
    标  题: 用WinDbg探索CLR世界 [2] 线程
    发信站: BBS 水木清华站 (Tue Mar  9 23:14:49 2004), 转信

    http://202.102.53.36/user8/flier_lu/main.asp?id=1370342

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

    [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)。这几种线程缓冲池中线程的概念,我们以后章节讨论线程池时再详细讨论。

    btw: 连续加了几天班,忙得头昏脑涨,今天总算有空继续写我的blog,呵呵
    --
    .    生命的意义在于   /\   ____\ /\_ \   /\_\    http://flier_lu.blogone.net.                            .  
    .        希望         \ \  \___/_\/\ \   \/_/__     __    _ _★              .  
    .        工作          \ \   ____\\ \ \    /\  \  /'__`\ /\`'_\              .  
    .      爱你的人         \ \  \___/ \ \ \___\ \  \/\ __// \ \ \/              .  
    .     和你爱的人         \ \___\    \ \_____\ \__\ \____\ \ \_\              .  
    .        ……             \/___/     \/_____/\/__/\/____/  \/_/ @nsfocus.com.  


    ※ 来源:·BBS 水木清华站 smth.org·[FROM: 211.167.254.*]
    上一篇
    返回上一页
    回到目录
    回到页首
    下一篇


       收藏   分享  
    顶(0)
      




    ----------------------------------------------

    -----------------------------------------------

    第十二章第一节《用ROR创建面向资源的服务》
    第十二章第二节《用Restlet创建面向资源的服务》
    第三章《REST式服务有什么不同》
    InfoQ SOA首席编辑胡键评《RESTful Web Services中文版》
    [InfoQ文章]解答有关REST的十点疑惑

    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2004/11/9 2:26:00
     
     GoogleAdSense
      
      
      等级:大一新生
      文章:1
      积分:50
      门派:无门无派
      院校:未填写
      注册:2007-01-01
    给Google AdSense发送一个短消息 把Google AdSense加入好友 查看Google AdSense的个人资料 搜索Google AdSense在『 Dot NET,C#,ASP,VB 』的所有贴子 点击这里发送电邮给Google AdSense  访问Google AdSense的主页 引用回复这个贴子 回复这个贴子 查看Google AdSense的博客广告
    2024/5/15 18:39:05

    本主题贴数1,分页: [1]

    管理选项修改tag | 锁定 | 解锁 | 提升 | 删除 | 移动 | 固顶 | 总固顶 | 奖励 | 惩罚 | 发布公告
    W3C Contributing Supporter! W 3 C h i n a ( since 2003 ) 旗 下 站 点
    苏ICP备05006046号《全国人大常委会关于维护互联网安全的决定》《计算机信息网络国际联网安全保护管理办法》
    62.500ms