在执行一行代码之前CLR做的68件事
因为CLR是一个托管环境,所以运行时中有几个组件需要在执行任何代码之前初始化。本文将介绍EE(执行引擎)启动程序,并详细检查初始化过程。68只是一个粗略的指南,它取决于您使用的运行时版本、启用了哪些功能以及其他一些东西。
样例代码
假设你有一个最简单的C#程序,在CLR将“Hello World”输出到控制台之前会发生什么?
using System; namespace ConsoleApplication
{
public class Program
{
public static void Main(string[] args)
{
Console.WriteLine("Hello World!");
}
}
}
进入EE(执行引擎)的代码路径
当.NET可执行文件运行时,通过以下代码路径进入EE:
- _CorExeMain() (the external entry point)
- call to _CorExeMainInternal()
- _CorExeMainInternal()
- call to EnsureEEStarted()
- EnsureEEStarted()
- call to EEStartup()
- EEStartup()
- call to EEStartupHelper()
- EEStartupHelper()
因此,我们在EEStartupHelper()中结束,它在高层执行以下操作(来自ceemain.cpp中的注释)---EEStartup负责运行时的所有一次性初始化:
- 创建默认和共享的appdomains。
- 加载mscorlib.dll并加载基本类型(System.Object…)
EE(执行引擎)启动程序的主要阶段
下面的列表包含了从EEStartupHelper()调用的所有单独函数(~500 L.O.C)。为了使它们更容易理解,我们将它们分为不同的阶段:
- 第1阶段-在运行其他任何东西之前,设置需要到位的基础设施
- 第2阶段-初始化核心低层组件
- 第3阶段-启动低级组件,即错误处理、Profiling API、调试
- 阶段4-启动主要组件,即垃圾收集器(GC)、AppDomains、安全性
- 第5阶段-最终设置,然后通知其他组件EE已启动
第1阶段-在运行其他任何东西之前,设置需要到位的基础设施
- Wire-up console handling - SetConsoleCtrlHandler(..) (
ifndef FEATURE_PAL) - Initialise the internal
SStringclass (everything uses strings!) - SString::Startup() - Make sure the configuration is set-up, so settings that control run-time options can be accessed - EEConfig::Set-up() and InitializeHostConfigFile() (
#if !defined(CROSSGEN_COMPILE)) - Initialize Numa and CPU group information - NumaNodeInfo::InitNumaNodeInfo() and CPUGroupInfo::EnsureInitialized() (
#ifndef CROSSGEN_COMPILE) - Initialize global configuration settings based on startup flags - InitializeStartupFlags()
- Set-up the Thread Manager that gives the runtime access to the OS threading functionality (
StartThread(),Join(),SetThreadPriority()etc) - InitThreadManager() - Initialize Event Tracing (ETW) and fire off the CLR startup events - InitializeEventTracing() and ETWFireEvent(EEStartupStart_V1) (
#ifdef FEATURE_EVENT_TRACE) - Set-up the GS Cookie (Buffer Security Check) to help prevent buffer overruns - InitGSCookie()
- Create the data-structures needed to hold the ‘frames’ used for stack-traces - Frame::Init()
- Ensure initialization of Apphacks environment variables - GetGlobalCompatibilityFlags() (
#ifndef FEATURE_CORECLR) - Create the diagnostic and performance logs used by the runtime - InitializeLogging() (
#ifdef LOGGING) and PerfLog::PerfLogInitialize() (#ifdef ENABLE_PERF_LOG)
第2阶段-初始化核心低层组件
- Write to the log
===================EEStartup Starting=================== - Ensure that the Runtime Library functions (that interact with ntdll.dll) are enabled - EnsureRtlFunctions() (
#ifndef FEATURE_PAL) - Set-up the global store for events (mutexes, semaphores) used for synchronisation within the runtime - InitEventStore()
- Create the Assembly Binding logging mechanism a.k.a Fusion - InitializeFusion() (
#ifdef FEATURE_FUSION) - Then initialize the actual Assembly Binder infrastructure - CCoreCLRBinderHelper::Init() which in turn calls AssemblyBinder::Startup() (
#ifdef FEATURE_FUSIONis NOT defined) - Set-up the heuristics used to control Monitors, Crsts, and SimpleRWLocks - InitializeSpinConstants()
- Initialize the InterProcess Communication with COM (IPC) - InitializeIPCManager() (
#ifdef FEATURE_IPCMAN) - Set-up and enable Performance Counters - PerfCounters::Init() (
#ifdef ENABLE_PERF_COUNTERS) - Set-up the CLR interpreter - Interpreter::Initialize() (
#ifdef FEATURE_INTERPRETER), turns out that the CLR has a mode where your code is interpreted instead of compiled! - Initialise the stubs that are used by the CLR for calling methods and triggering the JIT - StubManager::InitializeStubManagers(), also Stub::Init() and StubLinkerCPU::Init()
- Set up the core handle map, used to load assemblies into memory - PEImage::Startup()
- Startup the access checks options, used for granting/denying security demands on method calls - AccessCheckOptions::Startup()
- Startup the mscorlib binder (used for loading “known” types from mscorlib.dll) - MscorlibBinder::Startup()
- Initialize remoting, which allows out-of-process communication - CRemotingServices::Initialize() (
#ifdef FEATURE_REMOTING) - Set-up the data structures used by the GC for weak, strong and no-pin references - Ref_Initialize()
- Set-up the contexts used to proxy method calls across App Domains - Context::Initialize()
- Wire-up events that allow the EE to synchronise shut-down -
g_pEEShutDownEvent->CreateManualEvent(FALSE) - Initialise the process-wide data structures used for reader-writer lock implementation - CRWLock::ProcessInit() (
#ifdef FEATURE_RWLOCK) - Initialize the debugger manager - CCLRDebugManager::ProcessInit() (
#ifdef FEATURE_INCLUDE_ALL_INTERFACES) - Initialize the CLR Security Attribute Manager - CCLRSecurityAttributeManager::ProcessInit() (
#ifdef FEATURE_IPCMAN) - Set-up the manager for Virtual call stubs - VirtualCallStubManager::InitStatic()
- Initialise the lock that that GC uses when controlling memory pressure - GCInterface::m_MemoryPressureLock.Init(CrstGCMemoryPressure)
- Initialize Assembly Usage Logger - InitAssemblyUsageLogManager() (
#ifndef FEATURE_CORECLR)
第3阶段-启动低级组件,即错误处理、Profiling API、调试
- Set-up the App Domains used by the CLR - SystemDomain::Attach() (also creates the DefaultDomain and the SharedDomain by calling SystemDomain::CreateDefaultDomain() and SharedDomain::Attach())
- Start up the ECall interface, a private native calling interface used within the CLR - ECall::Init()
- Set-up the caches for the stubs used by
delegates- COMDelegate::Init() - Set-up all the global/static variables used by the EE itself - ExecutionManager::Init()
- Initialise Watson, for windows error reporting - InitializeWatson(fFlags) (
#ifndef FEATURE_PAL) - Initialize the debugging services, this must be done before any EE thread objects are created, and before any classes or modules are loaded - InitializeDebugger() (
#ifdef DEBUGGING_SUPPORTED) - Activate the Managed Debugging Assistants that the CLR provides - ManagedDebuggingAssistants::EEStartupActivation() (
ifdef MDA_SUPPORTED) - Initialise the Profiling API - ProfilingAPIUtility::InitializeProfiling() (
#ifdef PROFILING_SUPPORTED) - Initialise the exception handling mechanism - InitializeExceptionHandling()
- Install the CLR global exception filter - InstallUnhandledExceptionFilter()
- Ensure that the initial runtime thread is created - SetupThread() in turn calls SetupThread(..)
- Initialise the PreStub manager (PreStub’s trigger the JIT) - InitPreStubManager() and the corresponding helpers StubHelpers::Init()
- Initialise the COM Interop layer - InitializeComInterop() (
#ifdef FEATURE_COMINTEROP) - Initialise NDirect method calls (lazy binding of unmanaged P/Invoke targets) - NDirect::Init()
- Set-up the JIT Helper functions, so they are in place before the execution manager runs - InitJITHelpers1() and InitJITHelpers2()
- Initialise and set-up the SyncBlock cache - SyncBlockCache::Attach() and SyncBlockCache::Start()
- Create the cache used when walking/unwinding the stack - StackwalkCache::Init()
阶段4-启动主要组件,即垃圾收集器(GC)、AppDomains、安全性
- Start up security system, that handles Code Access Security (CAS) - Security::Start() which in turn calls SecurityPolicy::Start()
- Wire-up an event to allow synchronisation of AppDomain unloads - AppDomain::CreateADUnloadStartEvent()
- Initialise the ‘Stack Probes’ used to setup stack guards InitStackProbes() (
#ifdef FEATURE_STACK_PROBE) - Initialise the GC and create the heaps that it uses - InitializeGarbageCollector()
- Initialise the tables used to hold the locations of pinned objects - InitializePinHandleTable()
- Inform the debugger about the DefaultDomain, so it can interact with it - SystemDomain::System()->PublishAppDomainAndInformDebugger(..) (
#ifdef DEBUGGING_SUPPORTED) - Initialise the existing OOB Assembly List (no idea?) - ExistingOobAssemblyList::Init() (
#ifndef FEATURE_CORECLR) - Actually initialise the System Domain (which contains mscorlib), so that it can start executing - SystemDomain::System()->Init()
第5阶段最终设置,然后通知其他组件EE已经启动了第4阶段-启动主要组件,即垃圾收集器(GC)、AppDomains、Security
- Tell the profiler we’ve stated up - SystemDomain::NotifyProfilerStartup() (
#ifdef PROFILING_SUPPORTED) - Pre-create a thread to handle AppDomain unloads - AppDomain::CreateADUnloadWorker() (
#ifndef CROSSGEN_COMPILE) - Set a flag to confirm that ‘initialisation’ of the EE succeeded -
g_fEEInit = false - Load the System Assemblies (‘mscorlib’) into the Default Domain - SystemDomain::System()->DefaultDomain()->LoadSystemAssemblies()
- Set-up all the shared static variables (and
String.Empty) in the Default Domain - SystemDomain::System()->DefaultDomain()->SetupSharedStatics(), they are all contained in the internal class SharedStatics.cs - Set-up the stack sampler feature, that identifies ‘hot’ methods in your code - StackSampler::Init() (
#ifdef FEATURE_STACK_SAMPLING) - Perform any once-only SafeHandle initialization - SafeHandle::Init() (
#ifndef CROSSGEN_COMPILE) - Set flags to indicate that the CLR has successfully started -
g_fEEStarted = TRUE,g_EEStartupStatus = S_OKandhr = S_OK - Write to the log
===================EEStartup Completed===================
执行用户代码
您的代码将通过以下代码流执行(在第一次被“JITted”之后):
- CorHost2::ExecuteAssembly()
- calling ExecuteMainMethod()
- Assembly::ExecuteMainMethod()
- calling RunMain()
- RunMain() (in assembly.cpp)
- eventually calling into you main() method
- full explanation of the ‘call’ process
转自:https://mattwarren.org/2017/02/07/The-68-things-the-CLR-does-before-executing-a-single-line-of-your-code/
在执行一行代码之前CLR做的68件事的更多相关文章
- 在执行一行代码之前CLR做的68件事[The 68 things the CLR does before executing a single line of your code]
待翻译,原文地址:http://mattwarren.org/2017/02/07/The-68-things-the-CLR-does-before-executing-a-single-line- ...
- 安装 Kali Linux 后需要做的 20 件事
安装 Kali Linux 后需要做的 20 件事 本文含有我觉得有用的每一件事情.本文分为三大部分: 专门针对Kali用户 Kali Linux是来自Debian的一个特殊版本,Kali Linux ...
- 安装 CentOS 7 后必做的七件事
原文 安装 CentOS 7 后必做的七件事 CentOS 是最多人用来运行服务器的 Linux 版本,最新版本是 CentOS 7.当你兴趣勃勃地在一台主机或 VPS 上安装 CentOS 7 后, ...
- 刚安装Fedora 23工作站后,你必须要做的24件事
[51CTO.com快译]Fedora 23工作站版本已发布,此后我们就一直在密切关注它.我们已经为新来读者介绍了一篇安装指南:<Fedora 23工作站版本安装指南> 还有一篇介绍如何从 ...
- 新手学习SEO要做的七件事是什么?
学习SEO可能不那么先进的编程,学习SEO不可能掌握网页设计,学习SEO不需要学习SEO DIV + CSS;不是一个困难的任务,但是在学习过程中,如果你想掌握SEO,那么我们要做的几件事. 1.学习 ...
- 在 PHP 7 中不要做的 10 件事
在 PHP 7 中不要做的 10 件事 1. 不要使用 mysql_ 函数 这一天终于来了,从此你不仅仅“不应该”使用mysql_函数.PHP 7 已经把它们从核心中全部移除了,也就是说你需要迁移到好 ...
- Ubuntu装完后要做的几件事
Ubuntu装完后要做的几件事 改hosts 无论哪里,改hosts都是第一件事,没hosts咋google.没google咋活.在终端输入命令 sudo gedit /etc/hosts在# The ...
- 安装完Ubuntu 14.04要做的九件事
www.linuxidc.com/Linux/2014-04/100411.htm 1.看看有哪些新特性 安装完之后的第一件事肯定是看看Ubuntu 14.04有哪些新的特性. Ubuntu 14.0 ...
- 亲身体验:digitalocean vps能做的10件事
我写过一篇亲身体验:digitalocean和linode评测哪个好,帮助不少网友选购价格便宜性能优异的免备案vps,相信大家对两家产品有所了解.vps的性能和用途远远超过传统的虚拟主机,你拥有独立I ...
随机推荐
- 【网络知识之五】TCP
TCP协议:传输控制协议. 一.TCP保证可靠性的机制1.校验和 TCP报头有16位检验和: 由发送端填充, 检验形式有CRC校验等. 如果接收端校验不通过, 则认为数据有问题. 此处的校验和不光包含 ...
- ng 引入query
ng 引入jquery 1.在项目中 npm install --save jquery 在对应组件中加入 import * as $ from "jquery"; 在angu ...
- vue中js文件中export常见方法及使用
js文件一般放静态资源或动态资源,我将在这两种不同资源的请求下以不同的方式export出来 第一种在js中使用function 动态资源 在vue文件中引用调用这些方法 import进来 在生命周期函 ...
- redis启动出现错误 can't chdir ...
启动redis出现以下错误:[15816] *********** # Can't chdir to ’**********‘ :No such file or directory 解决方法:手动创建 ...
- maven的基础入门
Maven是Java世界中一个很好使的项目管理工具,关于[好使]这个特性从项目的使用量上就能体现出来,虽然说现在有更好使的Gradle,但是Maven的地位也不会那么轻易被撼动,支持者还是多多. Ma ...
- javascript(五)表达式
表达式 (expression) JavaScript中的一个短语, JavaScript解释器会将其计算(evaluate) 出一 个结果.程序中的常量是最简单的一类表达式.变量名也是一种简单的表达 ...
- 我用Bash编写了一个扫雷游戏
我在编程教学方面不是专家,但当我想更好掌握某一样东西时,会试着找出让自己乐在其中的方法.比方说,当我想在 shell 编程方面更进一步时,我决定用 Bash 编写一个扫雷游戏来加以练习. 我在编程教学 ...
- Jenkins 任务定时
在项目配置中选择 Build Triggers 下勾选 Build periodically,可以对项目进行定时构建设置.构建设置详细可通过右边的问号符号进行查看. 定时构建字段遵循 cron 的语法 ...
- Jpa的简介
Jpa:是用于数据持久化的一组标准接口. 1.HelloWorld的编写 创建EntityManagerFactory 创建EntityManager 开启事务 数据持久化 提交事务 关闭Entity ...
- logger(一)slf4j简介及其实现原理
一.slf4j简介 slf4j(Simple logging facade for Java)是对所有日志框架制定的一种规范.标准.接口,并不是一个框架的具体的实现,因为接口并不能独立使用,需要和具体 ...