在执行一行代码之前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 ...
随机推荐
- 手把手教你 通过 NuGet.Server 包 搭建nuget服务器,并使用桌面工具上传 nuget 包,免命令行
新建web项目 工具:VS2013 版本:.Net Framework 4.6,低版本也行,不过要找到对应版本的Nuget.Server 装了NuGet客户端(百度如何安装) WebForm或MVC都 ...
- django实战(三)--删除和批量删除
上一节我们完成了带分页的模糊查询,本节我们继续删除操作. 同样的,先给出各个模块的代码(上一节的就不在贴出了):urls.py path('curd/delete/',views.curd_delet ...
- linux php composer安装和使用教程
linux php composer安装和使用教程建议在linux下 下载后 然后再下载到本地 win上最好别用composer下载速度超级慢 或者根本下不动 项目依赖包 ...
- Navicat Premium 12 安装与激活
一.Navicat Premium 12下载 官方下载地址:https://www.navicat.com.cn/download/navicat-premium 百度云盘:https://pan.b ...
- HTML -------- 标签、元素、属性,
HTMl 中的标签.元素.属性, one.标签 :HTML是由一套标记标签 (markup tag)组成,通常就叫标签 标签由开始标签和结束标签组成 <p> 这是一个开始标签 </p ...
- scala的应用--UDF:用户自定义函数
在window10下安装了hadoop,用ida创建maven项目. <properties> <spark.version>2.2.0</spark.version&g ...
- 【IntelliJ IDEA】idea部署服务到Tomcat的工作原理
参考地址: https://blog.csdn.net/qq_41116058/article/details/81435084 为什么idea部署服务到tomcat时候,一定要修改Applicati ...
- 一段不错的代码JS的顶部轮播广告
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- file 从InputStream读取byte[]示例
file 从InputStream读取byte[]示例 分类专栏: java基础 public static byte[] getStreamBytes(InputStream is) throw ...
- 关于VS C++中项目属性的一些名称的含义
这个属性页(Alt + F7)界面下的$开头的内容的含义 $(Platform), X64或X86类似的. $(SolutionDir),.sln的位置 $(Configuration), Debug ...