<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      Windbg+Rotor:Managed Process中的各種Special Threads分析

      這幾天Oracle培訓(xùn),數(shù)據(jù)庫功力倒是沒太大長進,倒是DebugWindows架構(gòu)和實現(xiàn)還有CLR的覺悟突飛猛進。

      開篇前首先3ksrick,他把他寫的一票經(jīng)典的文章都發(fā)到sscli.cnblogs.com團隊里面來了。Rick可是我在看雪bbs上面久仰的大牛由于寫的文章時間在創(chuàng)建團隊的時間之前,故需要翻到第一頁才能看到rick的文章。

       

             首先就從sscliTLS預(yù)先定義的一個結(jié)構(gòu)體說起了:

       

          enum TlsThreadTypeFlag // flag used for thread type in Tls data

      {

          ThreadType_GC = 0x00000001,

          ThreadType_Timer = 0x00000002,

          ThreadType_Gate = 0x00000004,

          ThreadType_DbgHelper = 0x00000008,

          ThreadType_Shutdown = 0x00000010,

          ThreadType_DynamicSuspendEE = 0x00000020,

          ThreadType_Finalizer = 0x00000040,

          ThreadType_ADUnloadHelper = 0x00000200,

          ThreadType_ShutdownHelper = 0x00000400,

          ThreadType_Threadpool_IOCompletion = 0x00000800,

          ThreadType_Threadpool_Worker = 0x00001000,

          ThreadType_Wait = 0x00002000,

      };

       

      這個枚舉類型的數(shù)據(jù)結(jié)構(gòu),是表示的TLS初始化參數(shù)中的Thread的類型。

             首先不說一個User App可以創(chuàng)建多少個不同類型的ThreadCLR中,當(dāng)一個托管Process在啟動之后,至少需要創(chuàng)建三種類型的Process:一個Main Thread用來啟動CLR和執(zhí)行托管代碼。一個CLR Debugger Helper thread。主要用來提供調(diào)試servicesFor interop debuggersjust as visual studiowindbg之類。另外就是一個finalizer thread,用來完成對各種可達和不可達的Object的析構(gòu)。

             這三種thread,是一個托管Process啟動之后最少需要創(chuàng)建的。另外,根據(jù)這個Process是干嘛的不同,還可能需要創(chuàng)建不同的threads來適應(yīng)不同的功能。例如webformwinform,涉及到I/OlocksynchronizationGCtimer以及ThreadPool的時候,都分別需要創(chuàng)建不同的threads

             Well,對于上面的thread,下面先來個簡單的敘述先:

       

      Finalizer ThreadThreadType_Finalizer = 0x00000040

      對于Finalizer Thread,主要是在EE在啟動的時候,GC Heap啟動的時候,由GC來創(chuàng)建的這個線程。

      等等,找一小白鼠演示下先,這里,選擇一個webform作為小白鼠,方便Threadpool的介紹和其余的一些Thread的演示:

       

      namespace TestWebApp

      {

          public partial class _Default : System.Web.UI.Page

          {

              protected void Page_Load(object sender, EventArgs e)

              {

                  Response.Write("test for web app");          

              }

          }

      }

       

      Windbg Attachaspnet_wp.exe這個Process

       

      0:007> !threads

      ThreadCount: 9

      UnstartedThread: 0

      BackgroundThread: 8

      PendingThread: 0

      DeadThread: 1

      Hosted Runtime: no

                                         

             ID     GC  Domain    APT Exception

         1    1 Enabled 0016ab98  Ukn (Threadpool Completion Port)

         7    2 Enabled 0016ab98  MTA (Finalizer)

         8    3 Enabled 0016ab98  MTA (Threadpool Completion Port)

        10    4 Enabled 0016ab98  Ukn

        XX    6 Enabled 0016ab98  Ukn (Threadpool Worker)

        12    5 Enabled 0016ab98  MTA (Threadpool Worker)

        13    7 Enabled 0016ab98  MTA (Threadpool Completion Port)

        16    8 Enabled 0016ab98  MTA (Threadpool Completion Port)

        11    9 Enabled 0016ab98  MTA (Threadpool Worker)

       

      這里為了顯示方便,去掉了一些列。上面顯示的托管Thread里面,第七個就是Finalizer Thread,用來析構(gòu)some Objects用的。來看看其堆棧調(diào)用情況:

       

      0:007> k

      ChildEBP RetAddr 

      0132fcd8 7c92e9ab ntdll!KiFastSystemCallRet

      0132fcdc 7c8094e2 ntdll!ZwWaitForMultipleObjects+0xc

      0132fd78 7c80a075 kernel32!WaitForMultipleObjectsEx+0x12c

      0132fd94 79f60b6a kernel32!WaitForMultipleObjects+0x18

      0132fdb4 79f34fb4 mscorwks!SVR::WaitForFinalizerEvent+0x7a

      0132fdc8 79ecb4a4 mscorwks!SVR::GCHeap::FinalizerThreadWorker+0x75

      0132fdd8 79ecb442 mscorwks!Thread::UserResumeThread+0xfb

      0132fe6c 79ecb364 mscorwks!Thread::DoADCallBack+0x355

      0132fea8 79ed5e8b mscorwks!Thread::DoADCallBack+0x541

      0132fed0 79ed5e56 mscorwks!ManagedThreadBase_NoADTransition+0x32

      0132fedc 79f6fd87 mscorwks!ManagedThreadBase::FinalizerBase+0xb

      0132ff14 79ecb00b mscorwks!SVR::GCHeap::FinalizerThreadStart+0xbb

      0132ffb4 7c80b683 mscorwks!Thread::intermediateThreadProc+0x49

      0132ffec 00000000 kernel32!BaseThreadStart+0x37

       

      啊哈,從下往上看,第一個是調(diào)用OSbase Thread的初始化方法。在托管Process的創(chuàng)建中,任何一個thread的創(chuàng)建都是基于一個base OS Thread的。關(guān)于soft threadhard thread!threads的區(qū)別,可以參見我以前的文章。還是有很大區(qū)別的。Then,第二行調(diào)用的是intermediateThreadProc,這個是任何一個soft thread在創(chuàng)建之前都需要調(diào)用的一個方法:

       

      DWORD __stdcall Thread::intermediateThreadProc(PVOID arg)

      {

          WRAPPER_CONTRACT;

       

          m_offset_counter++;

          if (m_offset_counter * offset_multiplier > PAGE_SIZE)

              m_offset_counter = 0;

       

          _alloca(m_offset_counter * offset_multiplier);

       

          intermediateThreadParam* param = (intermediateThreadParam*)arg;

       

          LPTHREAD_START_ROUTINE ThreadFcnPtr = param->lpThreadFunction;

          PVOID args = param->lpArg;

          delete param;

       

          return ThreadFcnPtr(args);

      }

       

      這個是Thread類中的intermediateThreadProc方法,是一個softThread創(chuàng)建的時候需要調(diào)用的。注意,這里的Thread不是由ThreadPool來創(chuàng)建的。對于Thread Pool創(chuàng)建一個Hard thread的時候,ThreadPoolMgr也有一個相同的intermediateThreadProc方法:

       

      DWORD __stdcall ThreadpoolMgr::intermediateThreadProc(PVOID arg)

      {

      WRAPPER_CONTRACT;

      //多調(diào)用了一組宏,來進行完整性的Contract的檢驗的。

          STATIC_CONTRACT_SO_INTOLERANT;

       

          offset_counter++;

          if (offset_counter * offset_multiplier > PAGE_SIZE)

              offset_counter = 0;

       

          _alloca(offset_counter * offset_multiplier);

       

          intermediateThreadParam* param = (intermediateThreadParam*)arg;

       

          LPTHREAD_START_ROUTINE ThreadFcnPtr = param->lpThreadFunction;

          PVOID args = param->lpArg;

          delete param;

       

          return ThreadFcnPtr(args);

      }

       

      這個方法,主要是用來避免P4 cpu 上面的64kb/1mb的命名問題。在EnableHyperThreading的時候,這個可以非常影響app的性能。

      GCHeap在啟動的時候,就啟動了Finalizer Thread

      DWORD __stdcall GCHeap::FinalizerThreadStart(void *args)

      這個方法的實現(xiàn),就不具體說了,比較麻煩的說。亂七八糟的檢查啊,初始化的東西比較多。同時也不是這里的重點。

       

      Debugger Helper ThreadThreadType_DbgHelper = 0x00000008

      還是上面的小白鼠,由于Thread太多了,一個一個的找起來不方便,就先用~*k命令把調(diào)用堆棧先都列了出來,找到了第四個線程是Debugger Helper Thread

       

      0:004> k

      ChildEBP RetAddr 

      00dbfe38 7c92e9ab ntdll!KiFastSystemCallRet

      00dbfe3c 7c8094e2 ntdll!ZwWaitForMultipleObjects+0xc

      00dbfed8 7c80a075 kernel32!WaitForMultipleObjectsEx+0x12c

      00dbfef4 79ed4b06 kernel32!WaitForMultipleObjects+0x18

      00dbff54 79ed4a63 mscorwks!DebuggerRCThread::MainLoop+0xcf

      00dbff84 79ed49a6 mscorwks!DebuggerRCThread::ThreadProc+0xca

      00dbffb4 7c80b683 mscorwks!DebuggerRCThread::ThreadProcStatic+0x82

      00dbffec 00000000 kernel32!BaseThreadStart+0x37

       

      從這個地方,可以看到,是mscorwks這個模塊啟動的這個Thread。這種在Managed Process種植入調(diào)試線程的方式,就有一些good tips和一些bad tips了。

      00dbff54 79ed4a63 mscorwks!DebuggerRCThread::MainLoop+0xcf

      這一句表明,在這個helper Thread的大部分時間,是在執(zhí)行一個loop循環(huán)來獲取外部debuggerrequest的。當(dāng)這個helper thread得到一個requets的時候,它就direct進入CLR的內(nèi)部data structure,得到一系列的結(jié)果,然后返回結(jié)果到debugger

      Since是由托管代碼啟動的,這個debugger helper thread只能提供對于mixed mode或者是managed debugger的支持。而對于windbg這樣的native debugger是不支持的。不過,如果如果windbg加載了sos或者是SIEExtPub或者是外部托管擴展調(diào)試模塊的話,那就另行討論了。

      另外提一下調(diào)試線程的“in-process model”和“out-process model”兩種調(diào)試模型的比較:

      CLRDebug Service里面“in-Process Model”就意味著這個debugger help threadee thread一樣運行在managed Process里面了,當(dāng)然,ee Thread也是提供一部分調(diào)試信息的。

      這樣的好處是顯而易見的,因為EE Thread也是提供一部分調(diào)試信息的,這樣以來,helper Thread就可以重用EE的這一部分代碼了。這樣比out-of-process調(diào)試模型更加容易得獲取了CLR的內(nèi)部的data stracture。性能的提升也是不用說了的。還有一個好處,就是可以于GC Thread在一些問題的處理上面更加好的協(xié)作和共享信息了,譬如,在對lock和在對synchronization objects的操作上面。同一個process里面的兩個thread總比不同process里面的線程交互起來方便吧。

      當(dāng)然,也是有bad tips的。由于一個helper debug thread只能存活在一個live process里面,這樣,在使用dump分析問題的時候,helper debugger的功能特性代碼就用不上鳥。What a pity..還有一個非常棘手的問題,由于inprocessmode的調(diào)試thread對于獲取托管代碼中的信息用起來比較方便,這樣,在interop的時候,托管代碼和native code交互起來之后,這整個調(diào)試模型就被破壞掉了,這也是為什么在vs 2003的時候,調(diào)試interop的時候經(jīng)常死鎖和特別慢的原因。

      還有一個問題,在需要完全調(diào)試這個process,下了一個斷點,所有的執(zhí)行都中斷的時候,這個thread還是運行著的。這樣,在進行壓力測試的時候,就帶來了麻煩了….

      額,還有一些問題,羅嗦起來就麻煩了扯遠了沒完沒了了,打住打住。

       

      Rotor里面,對于這個helper debugger thread的實現(xiàn),是藏在一個陰暗的角落了(debug/ee/rcthread.cpp):

       

      /*static*/ DWORD WINAPI DebuggerRCThread::ThreadProcStatic(LPVOID)

      {

      // We just wrap the instance method DebuggerRCThread::ThreadProc

      //為了保持一致性的宏的合同檢查

          WRAPPER_CONTRACT;

          BEGIN_SO_INTOLERANT_CODE_NO_THROW_CHECK_THREAD_FORCE_SO();

            

             //這個地方是上面的枚舉類型了,設(shè)置clr的這個thread flag,標(biāo)識其類型為調(diào)試線程。

      ClrFlsSetThreadType(ThreadType_DbgHelper);

      //寫入調(diào)試日志。

          LOG((LF_CORDB, LL_EVERYTHING, "ThreadProcStatic called\n"));

            

      DebuggerRCThread* t = (DebuggerRCThread*)g_pRCThread;

             //這句才是重點,又調(diào)用別的地方去了,不繼續(xù)找了,查看堆棧

          t->ThreadProc(); // this thread is local, go and become the helper

         

          END_SO_INTOLERANT_CODE;

          return 0;

      }

       

      ThreadPool threads and relative threads

      這個是一個比較大的部分。ThreadPool Thread和一些由ThreadPool啟動的相關(guān)的Threads。這些thread,并不是一個托管Process必須有的Thread,這取決于一個Host到宿主的進程如何使用CLR的特性和功能了。

      還有,some of 這些thread type啟動之后,更加CPU模式,所處理的工作和一些用戶的配置文件,這些同類型的thread,可以只有一個,也可以有多個。例如以前提到的在多cpu的時候,如果GC運行在Server mode的話,一個cpu對應(yīng)一個gc thread的,管理一個GC Heap和一個LOH

      啊哈,剛才在在代碼里面找到了一個枚舉類型的結(jié)構(gòu)體:

       

      enum ThreadpoolThreadType

      {

          WorkerThread,

          CompletionPortThread,

          WaitThread,

          TimerMgrThread

      };

       

      這個枚舉類型的結(jié)構(gòu)體還是表明了很多信息的。^_^

       

      這些由ThreadPool啟動的threadtype就多了,主要有上面的四種類型:包括wait Thread,對應(yīng)上面的Thread Type waitWait Thread用來處理同步等待,這種類型的Thread可以有多個。WorkerThread,這些worker thread是用來執(zhí)行托管代碼的,根據(jù)需要執(zhí)行的功能的不同,可以有多個。Completion port threads,這些線程用來處理I/Onetwork Port相關(guān)的功能。MsRotor1.1里面是沒有這個東西的..2.0里面有不用說。

      另外,和worker thread匹配的,還有一個叫做gate threadthread。這個thread本身意義上面講,也是ThreadPool創(chuàng)建的,但是卻不屬于ThreadPoolThreadType。因為,worker thread并不是由ThreadPool直接創(chuàng)建管理的,worker thread是由Gate Thread創(chuàng)建并且管理的。因為根據(jù)程序的功能不同,worker thread可以多種多樣而且有很多。來個分層設(shè)計,我喜歡。最后一個就是timer thread了。這個是用來控制timer queue的,只能有一個。

      具體的,就不一一介紹這些線程的實現(xiàn)和功能了,太多了。按照上面講解的思路和方法,可以得到的挺清楚。如有疑問可以follow commets

       

      AppDomain Unload Helper Thread (ThreadType_ADUnloadHelper = 0x00000200)

      這個Thread,是幫助AppDomain卸載用的。在CLR1.0中,如果需要將一個用戶啟動的AppDomain卸載的話,就會在System Domain中創(chuàng)建一個Worker Thread,用這個Thread來完成AppDomain的卸載工作。當(dāng)目標(biāo)AppDomain被卸載了之后,這個Thread就死掉了。而在Rotor里面,則是專門的用一個AppDomain Unload Helper Thread來完成這個工作的。關(guān)于AD的卸載步驟和細(xì)節(jié),以后在研究這個問題。

       

      GC Thread

      根據(jù)托管Process是運行的workstation模式的gc還是server模式的gc,還有一種用叫做concurrent模式的GC,這種模式的GCRotor里面是沒有的。

       

      另外,還有一些RPC thread和一些LRPC threads

      最后的剩下的,很大一部分就是COM Threads 

             額,到吃飯的點了,催吃飯去了,收尾收的有點急,虎頭蛇尾的感覺…………后續(xù)吧。 

             lbq1221119@4/12/2008 11:52 AM

             首發(fā):sscli.cnblogs.com

      posted on 2008-04-12 18:12  lbq1221119  閱讀(3513)  評論(11)    收藏  舉報

      導(dǎo)航

      主站蜘蛛池模板: 性色在线视频精品| 国产精品三级国产精品高| 毛片在线播放网址| 九九热视频免费在线播放| 亚洲国产成人久久综合野外| 日韩人妻无码一区二区三区99| 少妇无码av无码专区在线观看| 97视频精品全国免费观看| 波多野42部无码喷潮| 99久久精品国产亚洲精品| 国产色无码专区在线观看| 国产成人精品一区二区秒拍1o | 精品人妻伦九区久久69| 在线a亚洲老鸭窝天堂| 人妻少妇精品视频专区| 国内精品久久久久电影院| 国产视频一区二区三区四区视频| 久久亚洲精品国产精品 | 国产精品99一区二区三区| 青青青爽在线视频观看| 国产成人精品午夜在线观看| 久久视频在线视频| 精品偷拍一区二区三区在| 无套后入极品美女少妇| 东源县| 久久亚洲精品11p| 九九热免费精品视频在线| 激情综合网五月婷婷| 欧美巨大极度另类| 亚洲无人区码一二三四区| 中文熟妇人妻av在线| 亚洲av中文乱码一区二| 一区二区三区四区五区自拍| 美女无遮挡免费视频网站| 无码国产精品一区二区免费虚拟vr | 亚洲天堂成人网在线观看| 被黑人巨大一区二区三区| 色综合色国产热无码一| 97精品伊人久久久大香线蕉| 黄色不卡视频一区二区三区| 亚洲AV高清一区二区三区尤物|