分享
 
 
 

谈WinDbg之AppDomain的创建过程

王朝system·作者佚名  2008-05-19
窄屏简体版  字體: |||超大  

我们知道 CLR 中 Assembly 是在名为 AppDomain 的逻辑空间中被载入运行的,而 AppDomain 是介于操作系统层面进程和线程概念之间,同时具有线程的轻便和进程的封闭性,使用者可以通过 AppDomain.CreateDomain 创建新的 AppDomain。这样一来就出现了一个鸡生单还是蛋生鸡的问题,这个 AppDomain.CreateDomain 方法肯定是要在一个载入了 AppDomain 类型的 AppDomain 里面被调用的,但这个 AppDomain 又是谁调用 AppDomain.CreateDomain 方法创建的呢?呵呵

我们可以使用 WinDbg + SOS 的 EEHeap 命令,通过列出 CLR 执行引擎的堆信息,获取当前运行的 AppDomain 情况。我们以下面这段代码为例

以下内容为程序代码:

//

// AppDomain.cs

//

using System;

public class EntryPoint

{

public static void Main(string[] args)

{

Console.Out.WriteLine("Hello AppDomain!"

;

Console.In.ReadLine();

}

}

这个典型的 CLR 程序的输出如下:

以下为引用:

0:003 !EEHeap

succeeded

Loaded Son of Strike data table version 5 from "E:WINDOWSMicrosoft.NETFrameworkv1.1.4322mscorwks.dll"

Loader Heap:

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

System Domain: 793e6fc8

LowFrequencyHeap:00960000(2000:00001000)

Size: 0x00001000(4096) bytes.

HighFrequencyHeap:00962000(8000:00001000)

Size: 0x00001000(4096) bytes.

StubHeap:0096a000(2000:00001000)

Size: 0x00001000(4096) bytes.

Total size: 0x3000(12288)bytes

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

Shared Domain: 793e83f8

LowFrequencyHeap:00990000(2000) 06c40000(10000:00007000)

Size: 0x00009000(36864) bytes.

HighFrequencyHeap:00992000(8000:00001000)

Size: 0x00001000(4096) bytes.

StubHeap:0099a000(2000:00001000)

Size: 0x00001000(4096) bytes.

Total size: 0xb000(45056)bytes

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

Domain 0: 147330

LowFrequencyHeap:00970000(2000) 06c60000(10000:00004000)

Size: 0x00006000(24576) bytes.

HighFrequencyHeap:00972000(8000:00004000)

Size: 0x00004000(16384) bytes.

StubHeap:0097a000(2000:00001000)

Size: 0x00001000(4096) bytes.

Total size: 0xb000(45056)bytes

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

Jit code heap:

Normal Jit:06c80000(10000:00002000)

Size: 0x00002000(8192) bytes.

Total size 0x00002000(8192)bytes.

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

Total LoaderHeap size: 0x1b000(110592)bytes

=======================================

generation 0 starts at 0x04aa1040

generation 1 starts at 0x04aa1034

generation 2 starts at 0x04aa1028

segment

begin allocated

size

04aa0000 04aa1028

04aa4000 00002fd8(12248)

Large object heap starts at 0x05aa1028

segment

begin allocated

size

05aa0000 05aa1028

05aa6000 0x00004fd8(20440)

Total Size

0x7fb0(32688)

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

GC Heap Size

0x7fb0(32688)

我们可以看到,虽然这个程序非常简单,没有自己创建任何 AppDomain,但实际上 CLR 已经有了三个 AppDomain:"System Domain", "Shared Domain" 和 "Domain 0"。而进一步使用 DumpDomain 命令查看三个 AppDomain:

以下为引用:

0:003 !DumpDomain 793e6fc8

Domain: 793e6fc8

LowFrequencyHeap: 793e702c

HighFrequencyHeap: 793e7080

StubHeap: 793e70d4

Name:

Assembly: 00158e48 [mscorlib]

ClassLoader: 00158f20

Module Name

79b66000 e:windowsmicrosoft.net rameworkv1.1.4322mscorlib.dll

0:003 !DumpDomain 793e83f8

Domain: 793e83f8

LowFrequencyHeap: 793e845c

HighFrequencyHeap: 793e84b0

StubHeap: 793e8504

Name:

0:003 !DumpDomain 147330

Domain: 00147330

LowFrequencyHeap: 00147394

HighFrequencyHeap: 001473e8

StubHeap: 0014743c

Name: appdomain.exe

Assembly: 0015c2c0 [appdomain]

ClassLoader: 00161008

Module Name

00161d50 d: empappdomain.exe

我们可以看到,System Domain 实际上是专门用于载入 mscorlib.dll 这个 BCL 基础库的;Shared Domain 暂时没有使用;而 Domain 0 则负责运行我们的目标 Assembly。我们可以猜测 System Domain 是 CLR 专门用来载入系统基础库的,而系统将进一步使用此 mscorlib 创建其他 AppDomain 以运行用户目标 Assembly。我们接下来看看 Rotor 的相关代码,是否能够予以印证。

在 CLR 启动时负责加载执行引擎的 EEStartup 函数(vmceemain.cpp:206)中,可以发现此函数首先在进行基础性初始化工作后,调用 SystemDomain::Attach 函数载入 SystemDomain,然后加载并初始化异常处理、JITer等等支持代码,最后会调用 SystemDomain::Init 函数完成初始化 SystemDomain 等等工作。

SystemDomain::Attach 函数(vmappdomain.cpp:912)主要完成四部分工作:初始化系统 stub 管理器和 SystemDomain 的静态成员变量;以全局静态数组 g_pSystemDomainMemory 的内存区,构造并初始化 SystemDomain 对象,并将指针保存到 m_pSystemDomain 静态变量中,用于以后判断 SystemDomain 是否被构造等功能使用;构造缺省的 AppDomain;构造 SharedDomain。函数的简要功能代码如下:

以下内容为程序代码:

SystemDomain*

SystemDomain::m_pSystemDomain = NULL;

static BYTE

g_pSystemDomainMemory[sizeof(SystemDomain)];

HRESULT SystemDomain::Attach()

{

// 判断 SystemDomain 是否已经构造

_ASSERTE(m_pSystemDomain == NULL);

if(m_pSystemDomain != NULL)

return COR_E_EXECUTIONENGINE;

// 初始化系统 stub 管理器和 SystemDomain 的静态成员变量

// ...

// 构造 SystemDomain 对象

m_pSystemDomain = new (&g_pSystemDomainMemory) SystemDomain();

if(m_pSystemDomain == NULL) return COR_E_OUTOFMEMORY;

// 初始化 SystemDomain 对象

HRESULT hr = m_pSystemDomain-BaseDomain::Init(); // Setup the memory heaps

if(FAILED(hr)) return hr;

m_pSystemDomain-GetInterfaceVTableMapMgr().SetShared();

// 构造缺省的 AppDomain

hr = m_pSystemDomain-CreateDefaultDomain();

if(FAILED(hr)) return hr;

// 构造 SharedDomain

hr = SharedDomain::Attach();

return hr;

}

值得注意的是,为了让 SystemDomain 的构造不会失败,SystemDomain 及其基类 BaseDomain 的构造函数都为空,而初始化代码放到 Init 方法中完成,CLR 中很多类型的代码都使用类似的模式将构造和初始化分离以保障构造成功。BaseDomain::Init 函数在 SystemDomain::Attach 中直接被调用以初始化 SystemDomain 的父类;SystemDomain::Init 函数则在上面提到的 EEStartup 函数末尾才被调用,待会再详细讨论。

BaseDomain::Init 函数(vmappdomain.cpp:310)除了要负责初始化 BaseDomain 对象的一大堆成员变量外,主要负担堆和缓存的初始化。CLR 中的堆,实际上是在每个 AppDomain 中存在的,这也是为什么我们刚刚可以使用 EEHeap 命令列举 AppDomain 的原因。在初始化 BaseDomain 之后,会将 SystemDomain 的接口 VTable 映射表设置为共享,这是因为 SystemDomain 负责载入的 mscorlib 中类型实际上是所以 AppDomain 中都需要使用到的。

接着 SystemDomain::Attach 会调用 SystemDomain::CreateDefaultDomain 函数(vmappdomain.cpp:2522)构造缺省的 AppDomain,也就是前面试验中的 "Domain 0",用作载入用户指定 Assembly 执行。此函数只是简单地调用 SystemDomain::NewDomain 函数以非 Managed 方式构造新的 AppDomain 实例;然后将此 AppDomain 设置为缺省的 AppDomain。

以下内容为程序代码:

HRESULT SystemDomain::CreateDefaultDomain()

{

HRESULT hr = S_OK;

// 防止多次初始化

if (m_pDefaultDomain != NULL)

return S_OK;

// 以非 Managed 方式构造新的 AppDomain 实例

AppDomain* pDomain = NULL;

if (FAILED(hr = NewDomain(&pDomain)))

return hr;

// 将此 AppDomain 设置为缺省的 AppDomain

pDomain-GetSecurityDescriptor()-SetDefaultAppDomainProperty();

m_pDefaultDomain = pDomain;

// ...

}

SystemDomain::NewDomain 函数(vmappdomain.cpp:2480)比较简单,构造 AppDomain 实例后,通知此

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
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- 王朝網路 版權所有