站长中国
设为首页 | 站长论坛

站长论坛 站长下载
您所在的位置: 站长中国 > 站长学院 > 网络编程 > NET专区 >  正文

 CLR探索系列之应用程序域世界(上):Windbg+SOS剖析揭示域世界
  2008年02月20日14:36:20  评论(0条) 字体:[ ]
相关热点: 世界 剖析 揭示 系列 应用程序 探索 Size: bytes.
    
  在CLR的世界中,有一系列的令人Amazing的技术和架构。其中,CLR对应用程序在内存中内存分配,执行模型,程序之间的交互等一系列的技术,值得每一个致力于DotNet平台的技术人员深究。
  编程人员在开发的过程中,如果把程序集的加载(Assemblies Load),反射(Reflection),寄宿(Hosting),应用程序域(AppDomain),这四种技术结合起来使用的话,不仅能更好的使用CLR这个平台提供的强大的功能,而且能够构建更安全,更健壮的应用程序代码。
  
  这篇博文里,就是使用托管代码的动态调试工具,来研究一下CLR内部AppDomain的世界。
  
  首先,从一个C#程序开始:
   class Program
   {
   static void Main(string[] args)
   {
   Program b = new Program();
   b.test();
   System.Console.ReadLine();
   }
  
   public void test()
   {
   int i = 67;
   System.Console.WriteLine((char)i);
   System.Console.WriteLine((char)67);
   i = 1;
   }
   }
  
  运行了这个应用程序以后,我们打开windbg,attach到这个托管进程。
  .load SOS
  加载SOS扩展调试模块,可以使用.chain指令查看加载是否正确。
  0:003> lm
  start end module name
  00400000 00408000 TestConcoleApp (deferred)
  76990000 76acd000 ole32 (deferred)
  77be0000 77c38000 msvcrt (deferred)
  省略若干
  77fc0000 77fd1000 Secur32 (deferred)
  78130000 781cb000 MSVCR80 (deferred)
  79000000 79045000 mscoree (deferred)
  79060000 790b3000 mscorjit (deferred)
  790c0000 79b90000 mscorlib_ni (deferred)
  79e70000 7a3d6000 mscorwks (deferred)
  查看下意境加载了的模块,然后使用ld命令把我们的调试符号文件载入。VS在编译生成一个Console App的时候,在debug模式的时候会在debug的bin目录下生成一个和应用程序同名的pdb文件。我们要做的,就是载入这个文件:
  
  0:003> ld TestConcoleApp
  *** WARNING: Unable to verify checksum for G:\Projects\TestConcoleApp\TestConcoleApp\bin\Debug\TestConcoleApp.exe
  Symbols loaded for TestConcoleApp
  
  有一个警告,咋这里先不管,再使用lm查看已经加载了的模块的时候,可以看到这个module的调试符号文件已经被加载上了。
  
  此时,我们可以查看下Excute Engine (CLR)的堆里面都有些什么东西,我们可以使用!EEHeap命令,EE的意思,就是CLI的执行引擎,也就是我们常说的CLR。这个命令可以查看到一个托管进程里面的garbage-collected 和 Loader heaps相关信息。
  0:003> !eeheap
  PDB symbol for mscorwks.dll not loaded
  Loader Heap:
  --------------------------------------
  System Domain: 7a38f918
  LowFrequencyHeap: Size: 0x0(0)bytes.
  HighFrequencyHeap: 00a62000(8000:1000) Size: 0x1000(4096)bytes.
  StubHeap: 00a6a000(2000:1000) Size: 0x1000(4096)bytes.
  Virtual Call Stub Heap:
   IndcellHeap: Size: 0x0(0)bytes.
   LookupHeap: Size: 0x0(0)bytes.
   ResolveHeap: Size: 0x0(0)bytes.
   DispatchHeap: Size: 0x0(0)bytes.
   CacheEntryHeap: Size: 0x0(0)bytes.
  Total size: 0x2000(8192)bytes
  /**********************************************
  Loader Heap 中的系统域。这个域和下面的Shared Domian一起,是对托管的宿主程序,以及托管代码不可见的。这个域加载了两个CLR执行中十分重要的Module,MSCorEE.dll和MScorwks.dll。MSCorEE.dll这个文件就是大家熟悉的shim,垫片。在CLR加载中起到的重要作用。这里就不分析了,大家可以参考别的文献的介绍。
  对于每个应用程序域,都会有自己的安全描述符,安全上下文以及默认的上下文。这三个部分可以支持一个应用程序域来自定义一个单独实施的安全策略,譬如,可以用来确保宿主程序在加载托管代码的时候不会对这些重要的数据结构造成破坏。
  **********************************************/
  --------------------------------------
  Shared Domain: 7a38fef0
  LowFrequencyHeap: 00a90000(2000:1000) Size: 0x1000(4096)bytes.
  HighFrequencyHeap: Size: 0x0(0)bytes.
  StubHeap: 00a9a000(2000:1000) Size: 0x1000(4096)bytes.
  Virtual Call Stub Heap:
   IndcellHeap: Size: 0x0(0)bytes.
   LookupHeap: Size: 0x0(0)bytes.
   ResolveHeap: 00aab000(5000:1000) Size: 0x1000(4096)bytes.
   DispatchHeap: 00aa7000(4000:1000) Size: 0x1000(4096)bytes.
   CacheEntryHeap: Size: 0x0(0)bytes.
  Total size: 0x4000(16384)bytes
  /**********************************************
  在共享域中,加载所有的应用程序域中都要使用到的assemblies,譬如MScorlib.dll。装载了System.Object,System.ValueType这样的基础类。
  **********************************************/
  --------------------------------------
  Domain 1: 154250
  LowFrequencyHeap: 00a70000(2000:2000) Size: 0x2000(8192)bytes.
  HighFrequencyHeap: 00a72000(8000:2000) Size: 0x2000(8192)bytes.
  StubHeap: Size: 0x0(0)bytes.
  Virtual Call Stub Heap:
   IndcellHeap: Size: 0x0(0)bytes.
   LookupHeap: Size: 0x0(0)bytes.
   ResolveHeap: Size: 0x0(0)bytes.
   DispatchHeap: Size: 0x0(0)bytes.
   CacheEntryHeap: Size: 0x0(0)bytes.
  Total size: 0x4000(16384)bytes
  /**********************************************
  对于特定的寄宿程序,可以根据需要创建多个应用的默认域。例如IE,Asp.Net,或者是SqlServer,可以创建一个或者是多个默认的域。域名默认情况下的name就是module的名称。
  在默认域中,应用程序执行的时候需要装载经来的assemblies可以被加载到这里。
  在每个应用程序域中,代码创建的对象不能直接访问另外的应用程序域中的代码。如果要访问这些代码,可以采用静态的委托,或者是appDomain的自己的方法来实现。
  **********************************************/
  --------------------------------------
  Jit code heap:
  LoaderCodeHeap: 00db0000(10000:1000) Size: 0x1000(4096)bytes.
  Total size: 0x1000(4096)bytes
  对于托管的应用程序,有两种把IL代码编译成本地代码的方式。一种是在第一次运行的时候,调用JIT模块来实时编译,编译好了的本地代码就放到这里。在PE文件中的相应的代码处,就用一个指针指引CLR到这里来找相关的编译好了的本地代码。第二中是安装的时候就编译成为本地代码。
  同时可以看到,Jit Heap占用很少的内存空间。
  --------------------------------------
  Module Thunk heaps:
  Module 790c2000: Size: 0x0(0)bytes.
  Module 00a72c24: Size: 0x0(0)bytes.
  Total size: 0x0(0)bytes
  --------------------------------------
  Module Lookup Table heaps:
  Module 790c2000: Size: 0x0(0)bytes.
  Module 00a72c24: Size: 0x0(0)bytes.
  Total size: 0x0(0)bytes
  
  --------------------------------------
  Total LoaderHeap size: 0xb000(45056)bytes
  总共的loader Heap的大小大概在45kb左右。
  =======================================
  Number of GC Heaps: 1
  generation 0 starts at 0x013b1018
  generation 1 starts at 0x013b100c
  generation 2 starts at 0x013b1000
  ephemeral segment allocation context: none
  下面的这两个segment对于应用程序域的其他代码来说是read only的,所以,这两部分的空间比较小。这块经常保存的是小的segement片段。除非你是很长很长的字符串。而大的object,则保持在LOH中。GC Heap,可以有多个。每个GC Heap中,都可以有一个LOH。
  而每个GC Heap的总大小=Segment占用的空间+LOH
   segment begin allocated size
  0014d720 790d5588 790f4b38 0x0001f5b0(128432)
  013b0000 013b1000 013b3ff4 0x00002ff4(12276)
  Large object heap starts at 0x023b1000
   segment begin allocated size
  023b0000 023b1000 023b3250 0x00002250(8784)
  Total Size 0x247f4(149492)
  ------------------------------
  GC Heap Size 0x247f4(149492)
  总共的GC堆大概150kb。
  ---------------------------------------------------------------------------------------------------------
  托管线程的内存结构:
  这里,简单的交代一下一个托管进程的内存结构。在创建了一个托管的应用程序的线程以后,首先默认情况下创建了最少3个应用程序域,就是系统域,共享域,和默认域。前两个对托管的用户代码来说是不可见的。当时,可以调用共享与中的assemblies。用户的托管代码,和模块被load到默认域中。一个托管的宿主可以根据需要创建一个或者是多个默认域。
  
  托管进程,线程(hard thread,soft thread),应用程序域,程序集,模块的关系
  托管进程,应用程序域,程序集,模块,这四个概念从左到右是一对多的关系。及一个托管可以对应多个应用程序域,一个appdomain可以对应多个assemblies,一个assembly可以对应多个modules。modules就是我们经常看的.exe或者是.dll。exe文件是windows下对PE文件格式扩展了的托管模块。modules也可以是托管的动态链接库文件。
  对于线程,情况有点特殊。这里,首先要区别一个概念,操作系统的进程创建的线程和System.Threading.Thread这个类表示的线程。这里,把操作系统创建的进程叫做hard thread,System.Threading.Thread这个类表示的线程叫做soft Thread。hard Thread和应用程序域的关系,是多堆多的关系。就是一个应用程序域中可以存在多个hard Thread。而一个hard Thread,也可以存在于多个应用程序域里面。而soft Thread,是由应用程序域中的assemblies创建,所以,它只存在于相应的应用程序域中。
  当一个系统的hard thread进入某个应用程序域中进行操作的时候,这个应用程序域就会实例化一个System.Threading.Thread类来完成这个线程对应的工作。
  
  应用程序域的环境变量属性:
  对于每个应用程序域,有一系列的Environment属性可以设置,通过设置这些属性,可以配置一个应用程序域的特性,来满足各种对于安全,性能等许多方面特别的需求。
  可以参考MSDN的这里:
  http://msdn2.microsoft.com/en-us/library/system.appdomain_properties.aspx
  获知应用程序域相关的所有的Properties。
  特别说明:应用程序域的动态目录:
  对于应用程序域的所有的属性,需要特别提到一个叫做DynamicDirectory 的属性。
  这个属性的生成,有两个部分,譬如我本机上面的一个asp.net宿主进程的缓存文件夹:
  C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files\mesapplication\8a8504fd\e1680364
  C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files\mesapplication这一部分,由一个叫做DYNAMIC_BASE的属性来定义。同时包含了这个应用程序域中加载的项目文件信息。
  后面的两部分8a8504fd\e1680364,根据项目文件的不同,由应用程序的APP_NAME这个属性来决定。
  这样何在一起,就构成了在调试的过程中,进程在本机的缓存文件夹。
  
  在接下来的下篇中,讲从如何实现的角度,以实例源代码来分析AppDomain的运行机制。
  
  
    做人要厚道,请注明转自酷网动力(www.ASPCOOL.COM)。


责任编辑:

收藏本文 打印 打印本文  推荐本文 告诉好友 投稿 投稿邮箱

站长排行

学院

新闻

专栏

盈利

[揭密网络黄链]中国留学生买凶专破日本
JSP语法(6)
超强弹出窗口代码,什么都挡不住
FLASH视觉特效实例之地震效果
贴吧发帖机使用教程(绝对原创)
关于数据分页(转自www.codeproject.co
ASP实现文件直接下载
Photoshop制作光感超酷效果水晶球
 遍历ASP.NET页面控件
永远的后门[经典]+查不出的后门
淘宝网卖家公然叫卖“艳照门”照片集
驳《百度Hi面世对腾讯有利》
Google绿色专家质疑黑色背景网页节省资
国内各IT企业办公环境揭秘(多图)
阿里妈妈广告卖主全攻略
站长创业源动力 主流站长站赏析
推荐阅读:80年小子的创业道理
Discuz!6.0猛将出击 最强论坛程序酷炫
我的网络,我的团队:专访李文明
百度新闻频道改版十天 流量止跌反弹翻
ECSHOP模板制作参考文档
悬挂阿里妈妈会否被百度惩罚
阿里妈妈是否是中小站长的救世主?
最强网店ECShop发新版 众多酷炫功能给
ECSHOP模板下载
土豆网,优酷网,爆米花等视频网站采集
DedeCms模板安装/制作概述
网上商店系统巅峰对决 ECShop vs ShopE
艰难的走在创业的路上 第一天
编程中国全站采集规则
性福联盟 一个不尊重站长的联盟
大脚:日赚100元—揭露最新firefox欺骗
大脚:垃圾站超级赚钱法之二—突破“站
大脚:垃圾站超级赚钱法之——前言
迅雷联盟、快车联盟收入对比
经理人必看的十个管理网站
Google Adsense的秘密 第二版
西联汇款兑付城市查询
不用SEO取得成功的10个步骤
关于做GOOGLE的五条经验
站长学院  网页设计 建站教程 图形图象 网络编程

Photoshop CS3
Photoshop CS3
不用Photoshop
不用Photoshop

DIV+CSS的开发方式 听听另外的
虚拟主机建站动易里快速生成的
VBScript特效代码 满屏幕乱跑
牛气!一个菜鸟站长的超强网站
创建、维护一个个人博客的“投
让网站流量稳步飙升的秘籍
网站推广的基本思想

新闻线索

如果你有站长界人事变动、重组并购、变革技术出现,以及产品投诉等重要新闻线索,请告诉我们,我们会给予特别关注。
0631-3653338
站长中国编辑部
站长中国24小时新闻热线: 13256307008